Unable to replace files in request - laravel

I have an odd one.. I add an audio file, which is an existing file in the request
$file = $request->file('file')[0];
$request->files->add(['audio' => $file]);
When I do dd($request->files->all()) I see newly added 'audio' element. However when I do dd($request->allFiles()) I see original array.
I have even added a replace method for files to the Illuminate\Http\Request to replace $files with no luck.
public function replaceFiles($files) {
$this->files = $files;
}
Am I missing something?
It is as if $request->files and $this->files within $request are two different things.
Just noticed that the problem is with $this->convertedFiles within Illuminate\Http\Request which can be resolved by changing allFiles() to something similar to
/**
* Get an array of all of the files on the request.
*
* #return array
*/
public function allFiles()
{
$files = $this->files->all();
return $this->convertedFiles && count($this->convertedFiles) == count($this->files->all())
? $this->convertedFiles
: $this->convertedFiles = $this->convertUploadedFiles($files);
}
I've decided to extend App\Http\Requests\Request with adjusted allFiles() that I have mentioned above

You can use merge function to add new data into the request object.
$request->merge(['index_name' => $variable]);

Related

How to overwrite bulk clone function for laravel backpack

I am trying to overwrite a bulk clone function.
I just want to clone some values, and the rest assign a static value. For example, I just want to clone the name and description values, and the date I want to assign it the current date.
And well I don't know how to do it.
use \Backpack\CRUD\app\Http\Controllers\Operations\BulkCloneOperation { bulkClone as traitBulkClone; }
public function bulkClone($id) {
// your custom code here
$this->traitBulkClone($id);
}
TLDR: The most efficient way would probably be to overwrite the replicate() method on your model. Note that it is not a Backpack method, but an Eloquent method that BulkCloneOperation uses to duplicate a particular entry.
WHY?
Inside the BulkCloneOperation that you're using, you'll notice the route calls the bulkClone() method, that itself is just making some calls to the replicate() method on the model. That means you have two options to override this behaviour:
(Option A). Override the bulkClone() method in your CrudController. This will override the behaviour only on that particular admin operation.
(Option B). Override the replicate() method in you Model. That way, any time replicate() is called (by your admin panel or any other part of your software), the duplication is done in the way you specified.
In most cases, I think Option B is more appropriate, since it would avoid future code duplication. Here's Laravel's replicate() method at this time, just copy-pasting it into your model and modifying it to fit your needs is the best solution, if you ask me:
/**
* Clone the model into a new, non-existing instance.
*
* #param array|null $except
* #return static
*/
public function replicate(array $except = null)
{
$defaults = [
$this->getKeyName(),
$this->getCreatedAtColumn(),
$this->getUpdatedAtColumn(),
];
$attributes = Arr::except(
$this->getAttributes(), $except ? array_unique(array_merge($except, $defaults)) : $defaults
);
return tap(new static, function ($instance) use ($attributes) {
$instance->setRawAttributes($attributes);
$instance->setRelations($this->relations);
$instance->fireModelEvent('replicating', false);
});
}

Deleting a File from Storage after Download

I'm working on a media asset management system. I want the user to be able to fill out a form with file width, height, extension and colorspace, then transform the image and serve it back as a download.
I can get that to work by responding to the Post-Request with the URL of the newly created file.
What I want is for that file to be deleted after download or after some time.
(Or, preferably, a way to use laravels download() Response, which I apparently can't use inside an Axios/Ajax post request).
Thanks for your help :)
There are two ways you can do this.
Let's assume you have a file in storage/app/download.zip:
1. Because Laravel uses Symfony's HttpFoundation internally, you can use the deleteFileAfterSend method:
public function download()
{
return response()
->download(storage_path('app/download.zip'))
->deleteFileAfterSend(true);
}
2. Create a Terminable Middleware that deletes the file after the download response was prepared.
class StorageDownload
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
\Storage::delete('download.zip');
}
}
You'll need to register the middlware and assign it to your route for it to work.
As for triggering the download using JavaScript, something as trivial as setting the window location will work:
axios
.post('files/export/' + file.id, formData)
.then(function() {
window.location = 'files/download/' + file.id
});
Don't worry, this will not navigate away from your current page, it will just trigger the download.
for me , i like to handle this case using cron
you can read details here
add any column to check it's been downloaded or not (e.g status with value 0 or 1)
and you can create accessor on your model to count the date diff
public function getRangeDateAttribute(){
$today = Carbon::now()->startOfDay();
$downloadDate = $this->created_at;
$datediff = $today->diffInDays($downloadDate);
return $datediff
}
then sample code inside task scheduling :
if($media->status == 1 || $media->rangeDate > 7 ){ //checking the status & range date passed specific days you wanted
do whatever you wanted here
}

Deleting first record in laravel eloquent

When I click on my first record to delete from my application, I get method not found error but when I click on another record apart from first one it easily gets deleted.
What is the issue?
Below is the code for Delete:
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
$video = Video::findOrFail($id);
$delete = $video->delete();
if ($delete){
return redirect()->back()->with('trueDelete','Data Not Deleted');
}else{
return redirect()->back()->with('falseDelete','Data Deleted Successfully');
}
}
While clicking on first record from list shows below error,
Route::get('delete-video/{id}','VideoController#destroy');
First of all, that is too much work you are putting into deleting the record. Check out the link below on the official docs to see how to delete in a single line.
https://laravel.com/docs/5.6/eloquent#deleting-models
As for the image, you have a
Method not allowed exception.
This means that, on the place you are deleting from link one, you are using a different route variable than the one specified in the web.php file. Check that you aren't confusing a GET and POST and/or PUT.

Translate controller class variables in zend framework 2

Let's say I have a controller and I want to define some const variables that hold some messages (eg error messages etc).
Is there a way to make it so they are translated?
An example class is defined bellow:
<?php
namespace Test\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
class AccountController extends AbstractActionController
{
protected $testError = 'There was an error while testing some stuff';
public function testAction(){
// I know i can use the following approach but I don't want to
// since I want to use a variable for readability issues.
// $testError = $this->getTranslator()->translate('There was an error..');
return new ViewModel();
}
/**
* Retrieve the translator
*
* #return \Zend\I18n\Translator\Translator
*/
public function getTranslator()
{
if (!$this->translator) {
$this->setTranslator($this->getServiceLocator()->get('translator'));
}
return $this->translator;
}
/**
* Set the translator
*
* #param $translator
*/
public function setTranslator($translator)
{
$this->translator = $translator;
}
}
So I want to have the testError translated. I know I can just use the message and translate it via the zend translator without using a variable, but still I want to store it in a variable for readability issues. Any help or other approaches to this?
Simply create a translations.phtml file in any directory in your project root and fill it something like that:
<?php
// Colors
_('Black');
_('White');
_('Green');
_('Light Green');
_('Blue');
_('Orange');
_('Red');
_('Pink');
In poedit, check Catalog Properties > Source keywords list an be sure _ character is exists. (Alias of the gettext method). In application, use $this->translate($colorName) for example.
When poedit scanning your project directory to find the keywords which needs to be translated, translations.phtml file will be scanned too.
Another handy approach is using _ method (gettext alias) to improve code readability. Example:
$this->errorMsg = _('There was an error..');
But don't forget to set the global Locale object's default locale value too when you initialising your translator instance first time in a TranslatorServiceFactory or onBootstrap method of the module:
...
$translator = \Zend\Mvc\I18n\Translator\Translator::factory($config['translator']);
$locale = 'en_US';
$translator->setLocale($locale);
\Locale::setDefault($translator->getLocale());
return $translator;
...
I don't quite understand what you mean:
$errorMessage = 'FooBarBazBat";
return new ViewModel(array(
'error' => $this->getTranslator()->translate($errorMessage)
));
would be a way to store the message inside a variable. But i really don't understand where your problem is.
Or do you mean having the translator as variable?
$translator = $this->getServiceLocator()->get('viewhelpermanager')->get('translate');
$errorMessage = $translator('FooBarBazBat');

Overwriting JControllerForm save() Method to Trim POST Data Has No Effect

I have a component that has a controller called MyproductControllerGeneralsetting which extends JControllerForm. Inside MyproductControllerGeneralsetting I am overwriting the save method from the parent class in order to modify $_POST data and then the overwriting method calls the parent class' save method to do the actual saving.
Here's the overwritten method in MyproductControllerGeneralsetting:
/**
* We overwrite the saved form data and trim them to avoid spaces
*/
public function save($key = null, $urlVar = null){
if($_POST['jform']){
foreach($_POST['jform'] as $key=>&$value){
$value = trim($value);
}
}
// Finally, save the processed form data (calls JControllerForm-save())
parent::save('id', $urlVar);
}
The thing is that even though I've trimmed each POST data field in this overwriting method, if I have some values submitted such as 'value ' (note the space in the end), they are not trimmed.
I've checked the save method of the JControllerForm class and it seems to be getting the data from POST here:
$data = $this->input->post->get('jform', array(), 'array');
Maybe that's the reason? Is this getting cached data or something?
Instead of trying to get the values from $_POST directly, try getting and setting the data in the same way the parent class does - using an internal pointer to a (shared) instance of the JInput class.
Here's a modified, working, overwritten save method:
/**
* We overwrite the saved form data and trim them to avoid spaces
*/
public function save($key = null, $urlVar = null){
if($_POST['jform']){
// Get the original POST data
$original = JRequest::getVar('jform', array(), 'post', 'array');
// Trim each of the fields
foreach($original as $key=>$value){
$original[$key] = trim($value);
}
// Save it back to the $_POST global variable
JRequest::setVar('jform', $postData, 'post');
}
// Finally, save the processed form data
return parent::save('id', $urlVar);
}
The controller is the wrong place for such things anyway, or is there a specific reason you want to do it in the controller?
Better look at the prepareTable function in the model. There you already have the table object with the properties to save and can sanitise them prior to saving.
Additional Info:
If you extend JControllerForm, you can specify
/**
* #since 1.6
*/
protected $view_item = 'item';
/**
* #since 1.6
*/
protected $view_list = 'items';
By default, the $view_item will equal to the context. The $view_list tries to guess a pluralized version of the $view_item. Usually by adding an s to the end.

Resources