I'm new in Laravel, and I'm doing a project for my university, and I've two problems when I try to delete:
First error: When I try to delete the records, only the first one (with ID 1) doesn't delete from the table, but the other if deleted from the table and I've already tried some things to fix the error, but I couldn't:
Controller.php:
public function destroy_int($inst_id)
{
$inst = InstitucionEntidadInt::where('id', $inst_id);
$inst->delete();
return redirect('/activities/cons_instituciones_int');
}
Web.php:
Route::delete('/delete_inst_int/{inst_id}', [InstEntController::class, 'destroy_int'])
->name('institucion_int.destroy');
Second error: In some forms, it's necessary to upload and save files in a database (so I save just the name in the database and the files are saved in the public path). And some of this input files are multiple, so I save the names in the database like a JSON (using the json_encode method):
//This is the way that I save the files
$files = [];
if ($request->hasFile('inst_docsoporteNac')) {
foreach ($request->file('inst_docsoporteNac') as $file) {
$name = time() . "_" . $file->getClientOriginalName();
$file->move(public_path('files/institucionesNac'), $name);
$files[] = $name;
}
}
$instentNact->docSoportes = json_encode($files);
So, I'm trying to implement the delete method and I need to delete the files from both places (from the DB and the public path), I don't know how I can do it and I've already tried some "solutions" that I read from some forums (like this).
Controller.php:
public function destroy_nac($inst_id)
{
$inst = InstEntNac::where('id', $inst_id);
$files = InstEntNac::where('id', $inst_id)->get('docSoportes');
foreach (json_decode($files) as $file) {
Storage::delete(public_path('files/institucionesNac/' . $file));
}
$inst->delete();
return redirect('/activities/cons_instituciones_nac');
}
This is the way that I'm using, but I'm getting an error "Object of class stdClass could not be converted to string".
I'll appreciate your solutions for these errors.
For the first error, you can add error handling using this code:
InstitucionEntidadInt::findOrFail($inst_id)->delete();
For the second error, json_decode returns by default stdClass object instead of array. You can tell the function to return array type with second boolean parameter setting it to true:
json_decode($files, true)
https://www.php.net/manual/en/function.json-decode.php
I am developing a file system management using laravel 8.
I created a function that accept file.
public function uploadExperiment(Request $request)
{
$file = $request->file('file');
$uniqueId = time();
$fileName = $file->getClientOriginalName();
$filePath = $uniqueId . '/' . $fileName;
Storage::disk('local')->put($filePath, file_get_contents($file));
return response()->json(["success"=>true]);
}
I need to track the uploaded size during the uploading process and this progress I need to save it in a database.
For example, If I want to upload a file with 2GB of size, It will takes time. So any idea about how to track it?
maybe do you want create this:
https://www.itsolutionstuff.com/post/php-laravel-file-upload-with-progress-bar-exampleexample.html
to get size file upload in laravel use:
$size = $request->file('file')->getSize();
maybe could use this for get % of your upload you can use jquery. but if you want to do in php, with this example i think that you have one idea that you could to do:
function timeout_trigger() {
var loaded = file.getLoaded(); // loaded part
p = parseInt(loaded / size);
$(".progress").css("max-width",p+"%");
$(".progress-view").text(p+"%");
if(p!=100) {
setTimeout('timeout_trigger()', 20);
}
}
timeout_trigger();
i think that you have one form and you send it with POST for this use this function.
I'm trying to display an image stored outside the 'public' folder in my view. These are simple profile images whose paths are stored in the DB. The path looks like
/Users/myuser/Documents/Sites/myapp/app/storage/tenants/user2/images/52d645738fb9d-128-Profile (Color) copy.jpg
Since the image is stored a DB column for each user, my first thought was to create an Accessor in the User model to return the image. I tried:
public function getProfileImage()
{
if(!empty($this->profile_image))
{
return readfile($this->profile_image);
}
return null;
}
That produced unreadable characters in the view. I also tried file_get_contents() in place of read file. Any suggestions about how this might be accomplished?
How about this (just tested it myself and it works):
The view:
<img src="/images/theImage.png">
Routes.php:
Route::get('images/{image}', function($image = null)
{
$path = storage_path().'/imageFolder/' . $image;
if (file_exists($path)) {
return Response::download($path);
}
});
Here is a slightly modified version of #Mattias answer. Assume the file is in the storage/app/avatars folder which is outside the web root.
<img src="/avatars/3">
Route::get('/avatars/{userId}', function($image = null)
{
$path = storage_path().'/app/avatars/' . $image.'.jpg';
if (file_exists($path)) {
return response()->file($path);
}
});
Probably needs and else. Also I have wrapped mine inside the middleware auth Route Group which means you have to be logged in to see (my requirements) but I could do with more control over when it is made visible, perhaps alter the middleware.
EDIT
Forgot to mention that this is for Laravel 5.3.
Here's what I came up with:
I'm trying to show the images in the view, not download. Here's what I came up with:
Note that these images are stored above the public folder, which is why we have to take extra steps to display the image in the view.
The view
{{ HTML::image($user->getProfileImage(), '', array('height' => '50px')) }}
The model
/**
* Get profile image
*
*
*
* #return string
*/
public function getProfileImage()
{
if(!empty($this->profile_image) && File::exists($this->profile_image))
{
$subdomain = subdomain();
// Get the filename from the full path
$filename = basename($this->profile_image);
return 'images/image.php?id='.$subdomain.'&imageid='.$filename;
}
return 'images/missing.png';
}
public/images/image.php
<?php
$tenantId = $_GET["id"];
$imageId = $_GET["imageid"];
$path = __DIR__.'/../../app/storage/tenants/' . $tenantId . '/images/profile/' . $imageId;
// Prepare content headers
$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, $path);
$length = filesize($path);
header ("content-type: $mime");
header ("content-length: $length");
// #TODO: Cache images generated from this php file
readfile($path);
exit;
?>
If somebody has a better way, please enlighten us!! I'm very interested.
I have uploaded a lot of images from the website, and need to organize files in a better way.
Therefore, I decide to create a folder by months.
$month = date('Yd')
file_put_contents("upload/promotions/".$month."/".$image, $contents_data);
after I tried this one, I get error result.
Message: file_put_contents(upload/promotions/201211/ang232.png): failed to open stream: No such file or directory
If I tried to put only file in exist folder, it worked. However, it failed to create a new folder.
Is there a way to solve this problem?
file_put_contents() does not create the directory structure. Only the file.
You will need to add logic to your script to test if the month directory exists. If not, use mkdir() first.
if (!is_dir('upload/promotions/' . $month)) {
// dir doesn't exist, make it
mkdir('upload/promotions/' . $month);
}
file_put_contents('upload/promotions/' . $month . '/' . $image, $contents_data);
Update: mkdir() accepts a third parameter of $recursive which will create any missing directory structure. Might be useful if you need to create multiple directories.
Example with recursive and directory permissions set to 777:
mkdir('upload/promotions/' . $month, 0777, true);
modification of above answer to make it a bit more generic, (automatically detects and creates folder from arbitrary filename on system slashes)
ps previous answer is awesome
/**
* create file with content, and create folder structure if doesn't exist
* #param String $filepath
* #param String $message
*/
function forceFilePutContents ($filepath, $message){
try {
$isInFolder = preg_match("/^(.*)\/([^\/]+)$/", $filepath, $filepathMatches);
if($isInFolder) {
$folderName = $filepathMatches[1];
$fileName = $filepathMatches[2];
if (!is_dir($folderName)) {
mkdir($folderName, 0777, true);
}
}
file_put_contents($filepath, $message);
} catch (Exception $e) {
echo "ERR: error writing '$message' to '$filepath', ". $e->getMessage();
}
}
i have Been Working on the laravel Project With the Crud Generator and this Method is not Working
#aqm so i have created my own function
PHP Way
function forceFilePutContents (string $fullPathWithFileName, string $fileContents)
{
$exploded = explode(DIRECTORY_SEPARATOR,$fullPathWithFileName);
array_pop($exploded);
$directoryPathOnly = implode(DIRECTORY_SEPARATOR,$exploded);
if (!file_exists($directoryPathOnly))
{
mkdir($directoryPathOnly,0775,true);
}
file_put_contents($fullPathWithFileName, $fileContents);
}
LARAVEL WAY
Don't forget to add at top of the file
use Illuminate\Support\Facades\File;
function forceFilePutContents (string $fullPathWithFileName, string $fileContents)
{
$exploded = explode(DIRECTORY_SEPARATOR,$fullPathWithFileName);
array_pop($exploded);
$directoryPathOnly = implode(DIRECTORY_SEPARATOR,$exploded);
if (!File::exists($directoryPathOnly))
{
File::makeDirectory($directoryPathOnly,0775,true,false);
}
File::put($fullPathWithFileName,$fileContents);
}
I created an simpler answer from #Manojkiran.A and #Savageman. This function can be used as drop-in replacement for file_put_contents. It doesn't support context parameter but I think should be enough for most cases. I hope this helps some people. Happy coding! :)
function force_file_put_contents (string $pathWithFileName, mixed $data, int $flags = 0) {
$dirPathOnly = dirname($pathWithFileName);
if (!file_exists($dirPathOnly)) {
mkdir($dirPathOnly, 0775, true); // folder permission 0775
}
file_put_contents($pathWithFileName, $data, $flags);
}
Easy Laravel solution:
use Illuminate\Support\Facades\File;
// If the directory does not exist, it will be create
// Works recursively, with unlimited number of subdirectories
File::ensureDirectoryExists('my/super/directory');
// Write file content
File::put('my/super/directory/my-file.txt', 'this is file content');
I wrote a function you might like. It is called forceDir(). It basicaly checks whether the dir you want exists. If so, it does nothing. If not, it will create the directory. A reason to use this function, instead of just mkdir, is that this function can create nexted folders as well.. For example ('upload/promotions/januari/firstHalfOfTheMonth'). Just add the path to the desired dir_path.
function forceDir($dir){
if(!is_dir($dir)){
$dir_p = explode('/',$dir);
for($a = 1 ; $a <= count($dir_p) ; $a++){
#mkdir(implode('/',array_slice($dir_p,0,$a)));
}
}
}
In my Product Class, there is a function called pictures() which returns the file address of the picture of a product. It's something like this:
public function picture()
{
$file = "images/pictures/products/" . $this->id . ".png";
if(file_exists($file))
return $file;
else
return false;
}
It works fine when running the code on the administration area of the website (which is located on /admin/ directory)
But when I call this function from the index.php which is not on the /admin/ directory it always returns false. What should I do? The only way I figured to solve this is by creating a parameter on the picture() function, like: picture($directory_prefix) then that way I'll call the function with picture("/admin/"). But there's gotta be a better way than this...
Place your resources in a directory under the web root. Then the path would be:
$file = $_SERVER['HTTP_HOST']."/images/pictures/products/" . $this->id . ".png";