I'm trying to find a way to attach a non-physical file to an email that's being made on the spot.
I'm using the following lines in my controller:
$columns = ['line1', 'line2'];
$rows = [
['line1' => 'first', 'line2' => 'second'],
['line1' => 'first', 'line2' => 'second'],
['line1' => 'first', 'line2' => 'second'],
];
Mail::to('email#email.com')->send(new ExportMail($columns, $rows));
And the following build function in the ExportMail class:
public function build()
{
$file = fopen('php://output', 'w'); // Tried w+ too
fputcsv($file, $this->columns);
foreach ($this->rows as $row) {
fputcsv($file, $row);
}
// I tried a couple of things:
return $this->view('emails.myTestMail')
->attach($file);
return $this->view('emails.myTestMail')
->attach(fopen($file, 'r'));
return $this->view('emails.myTestMail')
->attach(fopen('php://output', 'r'));
return $this->view('emails.myTestMail')
->attach(file_get_contents($file));
return $this->view('emails.myTestMail')
->attach(file_get_contents(fopen($file, 'r')));
return $this->view('emails.myTestMail')
->attach(file_get_contents(fopen('php://output', 'r')));
}
But none if it works so I'm beginning to question if there is a way to send an email with a file that is never physically saved.
You can attach file data directly with the attachData method documented here:
https://laravel.com/docs/9.x/mail#raw-data-attachments
I use this regularly to attach dynamically generated PDF files, for example.
You should be able to do something like this:
return $this->view('emails.myTestMail')
->attachData($yourCsvData, "attachment.csv");
Also, I think you want to look at how you are generating your CSV data. Right now using php://output the CSV data will be sent out to the browser immediately, not stored in a variable.
There are a couple ways you can solve this, output buffering being one, or using php://temp instead, or using one of many CSV libraries (like https://csv.thephpleague.com/). I put together a fully working example for you here using php://temp:
https://laravelplayground.com/#/snippets/aa5b6594-4493-4ca4-9d12-837c102b7cc5
Expand the rawAttachments attribute on that Message on the right, and you'll see the attached CSV file.
Related
I am trying to create the pdf, using the domPDF library, for each single client present in the table of my application. So far everything ok!
When I go to save the pdf I want the name of the pdf document to be saved as:
name_client_surname_client.pdf,
so if for example I have a client named Alex Haiold, the document must be saved as Alex_Haiold.pdf
To do this, since I am passing the single client in the controller, as shown below, I tried to write
return $pdf->download('client->surname client->name.pdf');
but it is saved as
client-_surname client-_name.pdf (then printing client-_surname client-_name).
Here my code:
public function generatePDF(Client $client)
{
$data = [
'title' => 'Welcome to LaravelTuts.com',
'date' => date('m/d/Y'),
'client' => $client
];
//dd($data);
$pdf = PDF::loadView('client.clientPDF', $data);
return $pdf->download('client->surname client->name.pdf');
}
Can anyone kindly help me?
$pdf = PDF::loadView('client.clientPDF', $data);
return $pdf->download($client->surname . ' ' . client->name . '.pdf');
On the first line, we are just making a view file. The file is resources/views/client.clientPDF.blade.php and we are feeding data to the view file by passing the variable $data to it.
After making the view, our next step is to download the pdf file. For doing this, we need to call the download method of the instance.
On the first parameter, we are passing the filename with extension(pdf).
ok so I am upping my Laravel and MVC skills..currently all this in the controller (i know its bad thats why I am here I am trying to do it better :D)
Receive Data from UI as post (Done)
I have to store a file (Done)
store that file ID and path in a Files Table (Done)
Create new record and use the above record ID using query builder(Done)
but should I keep this in the controller or does this belong in the model specificlaly getting the files and storing the record etc.
do i build it the long way in the controller and use save()?
or return from a new model for files and pass that through on return (this i feel is best way ).
FileModel (To be built)
saves files returns file ID from file table
Business Model saves buisness data
controllerfile:
use /app/fileModel
$fileStored = call file model and passes request->file
for storing
$businessFile = $fileStored;
Save()
I think I have answered my own question but I am just making sure.
I am known for coding in anti patterns so I am asking for a bit of guidance not code thank you
Also if anyone knows of a place to just discuss laravel stuff so not to put here I would love a a good conversation, some my questions may seem stupid, I just need a soundboard at times.
ok so this works and is my solution.
public function create(Request $request)
{
//get files from request
$Match1 = $request->file('Match1')->store('media/scores');
$Match2 = $request->file('Match2')->store('media/scores');
$Match3 = $request->file('Match3')->store('media/scores');
//build collection array to loop through saving them
$collection = collect([$Match1,$Match2,$Match3]);
// store return paths in to new array
$mediapaths = array();
//loop through collections saving details in to files table pushing to the paths array
foreach($collection as $MatchScore) {
$ScoresSaved = Files::create([
'user_id' => $request->userID,
'file_name' => $request->title,
'type' => 'png',
'category_id'=>3,
'path' => $MatchScore,
'is_public'=>0
]);
array_push($mediapaths, $ScoresSaved);
}
//Save the score with new media path to the model
$scores = new Scores;
$scores->tournament=22;
$scores->round='Finals';
$scores->homeArcade=2578;
$scores->homePlayer=2;
$scores->opponenet=2;
$scores->Match1=$mediapaths[0]['id'];
$scores->Match2=$mediapaths[1]['id'];
$scores->Match3=$mediapaths[2]['id'];
$scores->Match1Score=22;
$scores->Match2Score=44;
$scores->Match3Score=88;
$scores->comments='testing full flow';
$scores->winner=2;
$scores->referee=3;
$scores->confirmed=1;
$scores->dispute=0;
$scores->submitedBy=2;
$scores->save();
return response()->json([
'result' => 'Success'
]);
}
While using the contentful laravel sdk the set include is not fetching any of the assets that belong to the entries I fetch. The code below (mine):
public function index()
{
$query = $this->query
->setContentType('gallery')
->setInclude(10);
$entry = $this->client->getEntries($query);
if (!$entry) {
abort(404);
}
$data = ['galleries' => $entry];
return view('welcome', ['data' => $data]);
}
The contenful example:
// contentful.php 3.0
$client = new Contentful\Delivery\Client(
'<content_delivery_api_key>',
'<space_id>',
'<environment_id>' // Defaults to "master" if ommitted
);
$query = (new Contentful\Delivery\Query())
->setInclude(2);
$entries = $client->getEntries($query);
my results:
[]
I expect for the previewImage and Images array to include the 'fields' that contain the location of the file. I only get 'sys'. I can't see why the include is not fetching this data. If i set setInclude to 20, over the limit i get an error. Below
What should i do differently? I achieved the desired results in a javascript frontend project, but with laravel i get nothing.
The include is actually working fine. Internally, linked entries/assets are represented using a Link object, which is resolved to an actual entry/asset as soon as you access the field (in your case, that's done with $entry->getPreviewImage(), which will return the Asset object that was loaded in your previous query).
This means that if you dump the entry you won't see the actual object you're expecting in the previewImage field, but everything will work fine if in regular use.
I have a form with input fields of type text and file. I have a problem of the filenames not saving in the database but everything else does. I vardumped $myForm and everything is there but the files, so I created another array with the filenames and merged it with $myForm. I then tried to set it to 'jform' but it doesn't seem to be working. Anyone have any ideas to why? Thanks!
controller.php
function save()
{
$jinput = JFactory::getApplication()->input;
$myForm = $jinput->get('jform', null, 'array');
//$files = $jinput->files->get('jform');
$file_array = ['image1' => 'test.png',
'image2' => 'test2.png'];
$merged_array = array_merge($myForm, $file_array);
$jinput->set('jform',$merged_array);
//or $jinput->post->set('jform',$merged_array); (this doesn't work either)
return parent::save();
}
Do not use $_POST unless you plan on writing extensive validation code to secure the user input.
Instead, use $jinput->get('jform', null, 'raw');
This will still apply some validation, but should keep your values in tact.
I'm building an admin utility for adding a bulk of images to an app I'm working on. I also need to to log certain properties that are associated with the images and then store it all into the database.
So basically the script looks into a folder, compares the contents of the folder to records in the database. All of the info must be entered in order for the database record to be complete, hence the form validation.
The validation is working, when there are no values entered it prompts the entry of the missing fields. However it happens even when the fields ARE filled.
I'm doing something a bit funny which may be the reason.
Because I'm adding a bulk of images I'm creating the data within a for loop and adding the validation rules within the same for loop.
Here is the results:
http://s75151.gridserver.com/CI_staging/index.php/admin_panel/bulk_emo_update
Right now I have default test values in the form while testing validation. The submit button is way at the bottom. I'm printing POST variable for testing purposes.
Here is the code:
function bulk_emo_update() {
$img_folder_location = 'img/moodtracker/emos/';//set an image path
$emo_files = $this->mood_model->get_emo_images('*.{png,jpg,jpeg,gif}', $img_folder_location); //grab files from folder
$emo_records = $this->mood_model->get_all_emos(); //grab records from db
$i=1; //sets a counter to be referenced in the form
$temp_emo_info = array(); //temp vairable for holding emo data that will be sent to the form
//loop through all the files in the designated folder
foreach($emo_files as $file) {
$file_path = $img_folder_location.$file;//builds the path out of the flder location and the file name
//loops through all the database reocrds for the pupose of checking to see if the image file is preasent in the record
foreach($emo_records as $record) {
//compairs file paths, if they are the
if($record->picture_url != $file_path) {
//FORM VALIDATION STUFF:
$rules['segment_radio['.$i.']'] = "required";
$rules['emo_name_text_feild['.$i.']'] = "required";
//populating the temp array which will be used to construct the form
$temp_emo_info[$i]['path'] = $file_path;
$temp_emo_info[$i]['name'] = $file;
}
}
$i++;
}
//sets the reference to validation rules
$this->validation->set_rules($rules);
//checks to see if the form has all it's required fields
if ($this->validation->run() == FALSE) { //if validation fails:
print_r($_POST);
//prepairs the data array to pass into the view to build the form
$data['title'] = 'Bulk Emo Update';
$data['intro_text'] = 'fill out all fields below. hit submit when finished';
$data['emos_info'] = $temp_emo_info;
$this->load->view('admin_bulk_emo_update_view',$data);
} else { // if it succeeds:
//printing for test purposes
print_r($_POST);
$this->load->view('form_result');
}
}
I'm new to codeigniter and php in general so if anything looks outrageously weird please tell me, don't worry about my feelings I've got thick skin.
if ($this->validation->run() == FALSE)
if you are calling the run() method of the validation class every time the script is run, will it ever return TRUE and run the else? Maybe a different return?
I'm a little cornfused by what's going on. Generally, if I'm having a problem like this, I will figure out a way to force the result I'm looking for. e.g. in your code, I'd force that else to run... once I get it to run, break down what happened to make it run. Rudimentary, but it has served me well.
You use array of rules in
$this->form_validation->set_rules()
wrong.
If you want to pass the rules in array you must stick to the key names like described here http://codeigniter.com/user_guide/libraries/form_validation.html#validationrulesasarray
So instead of
$rules['input_name'] = "required"
try this:
array(
'field' => 'input_name',
'label' => 'Name that you output in error message',
'rules' => 'required'
)