CakePHP Variable becomes empty - php

<?php
class UploadsController extends AppController {
var $name = 'Uploads';
var $components = array('Auth');
var $uses = array('Upload');
function beforeFilter() {
$this->Auth->allow('*');
}
function upload($event) {
App::import('Vendor', 'UploadedFiles', array('file' => 'UploadedFiles.php'));
$user = $this->Auth->user('id');
$this->set('user', $user);
if(!$this->Auth->user()) { $this->Session->setFlash(__('Please login.', true)); }
echo $user;
echo $event;
$vardir = date('d-m-Y');
$dir = 'img/gallery/'.$vardir.'/';
$thmbdir = 'img/gallery/'.$vardir.'/thumbnails/';
if(!is_dir($dir)) {
mkdir($dir, 0777);
mkdir($thmbdir, 0777);
}
$galleryPath = $dir;
$absGalleryPath = realpath($galleryPath) . '/';
$absThumbnailsPath = realpath($galleryPath . 'thumbnails/') . '/';
//Iterate through uploaded data and save the original file, thumbnail, and description.
while(($file = UploadedFiles::fetchNext()) !== null) {
$fileName = $file->getSourceFile()->getSafeFileName($absGalleryPath);
$file->getSourceFile()->save($absGalleryPath . '/' . $fileName);
$thumbFileName = $file->getThumbnail(1)->getSafeFileName($absThumbnailsPath);
$file->getThumbnail(1)->save($absThumbnailsPath . '/' . $thumbFileName);
$this->Upload->create();
$this->Upload->set(array(
'name' => $absGalleryPath . $fileName,
'width' => $file->getSourceFile()->getWidth(),
'height' => $file->getSourceFile()->getHeight(),
'description' => $file->getDescription(),
'event_id' => $event,
'user_id' => $user
));
$this->Upload->save();
}
}
}
Check the last part of the code where I try to save to the database. It doesn't save because $event and $users become empty. But when I echo them (line 17 and 18), they do appear on the page with correct values. It seems that they are being 'erased' in the while loop...
If I put some dummy data for 'event_id' => '123' and 'user_id' => '123', the scripts saves successfully. But if I use the variables, it doesn't save. What happens with my variables? Any idea?
Thanks

I'm guessing there's an error in your model. Try creating the array first, and printing it, and see if it creates the array correctly. Then make sure your model matches the array, ie. that the field types match the field types you input. '123' isn't the same as 123, since '123' is a string, and 123 is an integer.

i can think of a couple things i'd try though it's not to say you haven't already.
echo $user and $event the line just before and just after the while loop, to verify the problematic line.
set the variables to another temp variable:
$t_user = $user;
$t_event = $event;
then try using the $t_ variables in the loop.

Related

How to get related Model id in Laravel factory

I am trying to save the image using faker in the storage folder. I want to keep the images inside the property ID folder. I have tried the below code but it is not working. It hangs the command prompt. The properties have multiple images and are a one-to-many relation. The code below is for the PropertyImageFactory class.
public function definition()
{
$property_id = $this->create(Property::class)->id;
return [
'name' => $this->faker->image(storage_path('app/property-images/'.$property_id), 200, 200, 'cats'),
'sort_order' => $this->faker->numberBetween(1, 10),
'created_at' => now(),
'updated_at' => now(),
];
}
Laravel documentation has 'user_id' => User::factory(), I can't use this because it returns an object and I can't concatenate to string.
Below is the code for the property seeder.
public function run()
{
Property::factory()
->has(Category::factory()->count(3))
->has(PropertyImage::factory()->count(3), 'images')
->count(5)
->create();
}
Laravel documentation has 'user_id' => User::factory(), I can't use this because it returns an object and I can't concatenate to string.
Yup, that will return a UserFactory object just as Property::factory() will return a PropertyFactory. What you want to do is call the create() method on the factory and get the id from the record that is created.
$proprty_id = (\App\Models\Property::factory()->create())->id;
Laravel extracts the ID from the SomeModel::factory(), that's all the magic of Laravel. To do this, you need to properly describe the SomeModelFatory. You can use: $property_id = Property::factory();
As far as I know faker->image no longer works, I can advise using an auxiliary class for image formation.
<?php
namespace App\Helpers;
use Faker\Factory;
use Illuminate\Support\Facades\File;
class Image
{
public static function imageUrl(
int $width = 640,
int $height = 480,
bool $randomizeColors = false,
bool $randomizeTxt = false,
string $format = 'jpg'
): string
{
$baseUrl = "https://dummyimage.com";
$size = "/{$width}x{$height}";
$colors = "/aaa/fff";
$format = '.' . preg_replace('~^\b(?:jpg|png|gif)$~', 'jpg', $format);
if ($randomizeColors) {
$backgroundColor = str_replace('#', '', Factory::create()->safeHexColor);
$foreColor = str_replace('#', '', Factory::create()->safeHexColor);
$colors = "/{$backgroundColor}/{$foreColor}";
}
return $baseUrl . $size . $colors . $format . ($randomizeTxt ? '&text=' . Factory::create()->word : '');
}
public static function fake(
string $dir = null,
int $width = 640,
int $height = 480,
bool $randomizeColors = false,
bool $randomizeTxt = false,
string $format = 'jpg',
bool $fullPath = false
)
{
$dir = is_null($dir) ? sys_get_temp_dir() : $dir;
if (!is_dir($dir) || !is_writable($dir)) {
throw new \InvalidArgumentException("Unable to write to directory $dir");
}
$name = md5(uniqid(empty($_SERVER['SERVER_ADDR']) ? '' : $_SERVER['SERVER_ADDR'], true));
$filename = $name . ".$format";
$filepath = $dir . DIRECTORY_SEPARATOR . $filename;
$url = static::imageUrl($width, $height, $randomizeColors, $randomizeTxt, $format);
try {
$image = file_get_contents($url, false, stream_context_create(['http' => ['timeout' => 10]]));
try {
if (!File::put($filepath, $image)) {
return false;
}
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
} catch (\Exception $e) {
throw new \Exception($e->getMessage());
}
return $fullPath ? $filepath : $filename;
}
}
and use:
public function definition()
{
$property_id = Property::factory();
$dir = storage_path('app' . DIRECTORY_SEPARATOR . 'public' . DIRECTORY_SEPARATOR . $property_id);
mkdir($dir, 755);
return [
'name' => (\App\Helpers\Image())->fake($dir, 200, 200),
'sort_order' => $this->faker->numberBetween(1, 10)
];
}

How to transfer a variable from 1 function to another in the controller?

It is not possible to transfer data from one controller to another. There is such a controller for filling mp3 files via Dropzone.JS:
public function upload(Request $request)
{
if (!$request->has('file')) {
return response()->json(['message' => 'Missing file'], 422);
}
$file = $request->file('file');
$extension = !is_null($file->extension()) ? $file->extension() : 'mp3';
$fileName = !is_null($file->getClientOriginalName()) ? rtrim($file->getClientOriginalName(), '.') : 'Unknown - Unknown.mp3';
$tracksPath = 'public/tracks/';
$globalPath = storage_path('app/public/tracks/');
$globalTrackPath = $globalPath . $fileName;
$file->move(storage_path('app/public/tracks'), $fileName);
$fileHash = sha1_file($globalTrackPath);
rename($globalTrackPath, $globalPath . $fileHash . '.' . $extension);
$track = GetId3::fromDiskAndPath('storage', 'app/public/tracks/' . $fileHash . '.' . $extension);
$t = $track->extractInfo();
$title = !empty($t['tags']['id3v2']['title']['0']) ? $t['tags']['id3v2']['title']['0'] : 'Unknown';
$artist = !empty($t['tags']['id3v2']['artist']['0']) ? $t['tags']['id3v2']['artist']['0'] : 'Unknown';
$band = !empty($t['tags']['id3v2']['band']['0']) ? $t['tags']['id3v2']['band']['0'] : '';
$album = !empty($t['tags']['id3v2']['album']['0']) ? $t['tags']['id3v2']['album']['0'] : '';
$year = !empty($t['tags']['id3v2']['year']['0']) ? $t['tags']['id3v2']['year']['0'] : '';
$genre = !empty($t['tags']['id3v2']['genre']['0']) ? $t['tags']['id3v2']['genre']['0'] : '';
$url = Storage::url($tracksPath . $fileHash . '.mp3');
if(!empty($track->getArtwork(true))) {
$tmpCoverFile = $track->getArtwork(true)->getPathname();
$coverPath = 'public/tracks/covers/';
$cover64Path = 'cover.jpg';
Storage::disk('local')->put($coverPath . '/' . $fileHash . '/' . $cover64Path, File::get($tmpCoverFile));
$cover = Storage::url($coverPath . $fileHash . '/' . $cover64Path);
} else {
$cover = '/vendor/songs-crud/images/none.png';
}
DB::table('songs_tracks')->updateOrInsert(
['hash' => $fileHash],
[
'release_id' => $request->id,
'image' => $cover,
'name' => $title,
'artist' => $artist,
'band' => $band,
'album' => $album,
'year' => $year,
'genre' => $genre,
'url' => $url,
'hash' => $fileHash,
'sortable' => '',
'slug' => $fileHash
]
);
$getTrackId = DB::table('songs_tracks')
->where('hash', $fileHash)
->first();
$id = !empty($getTrackId->id) ? $getTrackId->id : 1;
return $id;
}
The function works fine, media files are uploaded to the server and records are added to the database table. I need to pass the id to another function that generates a JSON file:
public function getTrackListJson(Request $request): \Illuminate\Http\JsonResponse
{
dd($this->upload());
$tracks = DB::table('songs_tracks')->where('id', $id)->first();
return response()->json([$tracks]);
}
I'm trying to print this function via dd(), but it gives the following error:
ArgumentCountError
Too few arguments to function SequelONE\SongsCRUD\app\Http\Controllers\Admin\TrackCrudController::upload(), 0 passed in /home/site.com/packages/sequelone/songs-crud/src/app/Http/Controllers/Admin/TrackCrudController.php on line 229 and exactly 1 expected
I can't figure out how to pass an instance of $request and do I need to pass it at all? Can anyone help with this?
When you call a function that requires parameter, or uses injection like the Laravel Request, then you need to pass it in when you call the function manually. Since you're already injecting Request $request on your getTrackListJson call, you can just pass that along.
dd($this->upload($request));
That might help
public function getTrackListJson(Request $request): \Illuminate\Http\JsonResponse
{
$id = $this->upload($request);
$tracks = DB::table('songs_tracks')->where('id', $id)->first();
return response()->json([$tracks]);
}

Upload file to server with variable path

I have a fileupload function that is supposed to save files in different locations depending on which form was submitted.
First of all, I have in the same view the two ActiveForms to submit a file with (different variable in the field):
<?php $form = ActiveForm::begin(['action' => \yii\helpers\Url::to(['upload', 'id' => $model->id, 'mod' => 1]), 'options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'file1')->fileInput(['style' => ''])->label(false) ?>
<?= Html::submitButton('Upload', ['class' => 'btn-success']) ?>
<?php ActiveForm::end(); ?>
and
<?php $form = ActiveForm::begin(['action' => \yii\helpers\Url::to(['upload', 'id' => $model->id, 'mod' => 0]), 'options' => ['enctype' => 'multipart/form-data']]) ?>
<?= $form->field($model, 'file2')->fileInput(['style' => ''])->label(false) ?>
<?= Html::submitButton('Upload', ['class' => 'btn-success']) ?>
<?php ActiveForm::end() ?>
To my understanding, this would then put those files in the variable in the corresponding model:
* #var file1
* #var file2
*/
class X extends \yii\db\ActiveRecord
{
/**
* #var UploadedFile file1 attribute
*/
public $file1;
/**
* #var UploadedFile file2 attribute
*/
public $file2;
with the 'action' pointing to upload, it should call the xController action:
public function actionUpload($id, $mod) {
$model = new X();
if($mod == 1){
$model->file1 = UploadedFile::getInstance($model, 'file1');
if($model->file1){
$path = 'uploads/docs1/'. $id .'/';
if(!is_dir($path)){
FileHelper::createDirectory($path);
$model->pwFile->saveAs($path . $model->file1->baseName . '.' . $model->file1->extension);
}else{
$files = \yii\helpers\FileHelper::findFiles($path);
if(empty($files) || is_null($files)){
$model->file1->saveAs($path . $model->file1->baseName . '.' . $model->file1->extension);
}else{
foreach($files as $file){
unlink($file);
}
$model->file1->saveAs($path . $model->file1->baseName . '.' . $model->file1->extension);
}
}
}
}else{
$model->file2 = UploadedFile::getInstance($model, 'file2');
if($model->file2){
$path = 'uploads/docs2/'. $id .'/';
if(!is_dir($path)){
FileHelper::createDirectory($path);
}
$model->file->saveAs($path . $model->file2->baseName . '.' . $model->file2->extension);
}
}
return $this->render('view', ['model' => $this->findModel($id)]);
}
This doesn't seem to work. The upload for file1 works alright, the file gets uploaded to the server and that's it. If I use the second form however, it loads the correct url but nothing gets saved on the server. What am I doing wrong?
You have a massive amount of duplicated code, which makes it harder to debug. I hacked away at it and I think the below is optimal. I've also changed a few things, which should be pretty easy for you to spot.
public function actionUpload($id, $mod) {
$model = new X();
if($mod == 1) {
$file = UploadedFile::getInstance($model, 'file1');
$path = 'uploads/docs1/'. $id .'/';
} else {
$file = UploadedFile::getInstance($model, 'file2');
$path = 'uploads/docs2/'. $id .'/';
}
if ($file->name != '') {
if(is_dir($path)){
$files = \yii\helpers\FileHelper::findFiles($path);
foreach($files as $file){
unlink($file);
}
}
FileHelper::createDirectory($path);
$file->saveAs($path . $file->name);
}
return $this->render('view', ['model' => $this->findModel($id)]);
}
I think this will work now, if not, give me a shout and I'll have another look.

How to get data attribute for div item on another page

I am using slim image cropper.
I have the following.
<div class="slim" data-service="async.php" data-ratio="3:2" data-size="600,400" data-row="">
<!-- <input type="hidden" id="rowID" name="rowID"> -->
<input type="file"/>
</div>
I added the data-row=" " and then in the jQuery I added the following.
$('.slim').attr('data-row', rowID);
That part is working fine, but now how do I retrieve the value of the data-row on the async.php page?
Here is ASYNC.php
<?php
// Uncomment if you want to allow posts from other domains
// header('Access-Control-Allow-Origin: *');
require_once('slim.php');
foreach(Slim::getImages() as $imagess) {
echo $imagess['meta']->data-row;
}
// Get posted data, if something is wrong, exit
try {
$images = Slim::getImages();
}
catch (Exception $e) {
// Possible solutions
// ----------
// Make sure you're running PHP version 5.6 or higher
Slim::outputJSON(array(
'status' => SlimStatus::FAILURE,
'message' => 'Unknown'
));
return;
}
// No image found under the supplied input name
if ($images === false) {
// Possible solutions
// ----------
// Make sure the name of the file input is "slim[]" or you have passed your custom
// name to the getImages method above like this -> Slim::getImages("myFieldName")
Slim::outputJSON(array(
'status' => SlimStatus::FAILURE,
'message' => 'No data posted'
));
return;
}
// Should always be one image (when posting async), so we'll use the first on in the array (if available)
$image = array_shift($images);
// Something was posted but no images were found
if (!isset($image)) {
// Possible solutions
// ----------
// Make sure you're running PHP version 5.6 or higher
Slim::outputJSON(array(
'status' => SlimStatus::FAILURE,
'message' => 'No images found'
));
return;
}
// If image found but no output or input data present
if (!isset($image['output']['data']) && !isset($image['input']['data'])) {
// Possible solutions
// ----------
// If you've set the data-post attribute make sure it contains the "output" value -> data-post="actions,output"
// If you want to use the input data and have set the data-post attribute to include "input", replace the 'output' String above with 'input'
Slim::outputJSON(array(
'status' => SlimStatus::FAILURE,
'message' => 'No image data'
));
return;
}
// if we've received output data save as file
if (isset($image['output']['data'])) {
// get the name of the file
$name = $image['output']['name'];
// get the crop data for the output image
$data = $image['output']['data'];
// If you want to store the file in another directory pass the directory name as the third parameter.
// $output = Slim::saveFile($data, $name, 'my-directory/');
// If you want to prevent Slim from adding a unique id to the file name add false as the fourth parameter.
// $output = Slim::saveFile($data, $name, 'tmp/', false);
// Default call for saving the output data
$output = Slim::saveFile($data, $name, 'images/modules/listings');
}
// if we've received input data (do the same as above but for input data)
if (isset($image['input']['data'])) {
// get the name of the file
$name = $image['input']['name'];
// get the crop data for the output image
$data = $image['input']['data'];
// If you want to store the file in another directory pass the directory name as the third parameter.
// $input = Slim::saveFile($data, $name, 'my-directory/');
// If you want to prevent Slim from adding a unique id to the file name add false as the fourth parameter.
// $input = Slim::saveFile($data, $name, 'tmp/', false);
// Default call for saving the input data
$input = Slim::saveFile($data, $name, 'images/modules/listings');
}
//
// Build response to client
//
$response = array(
'status' => SlimStatus::SUCCESS
);
if (isset($output) && isset($input)) {
$response['output'] = array(
'file' => $output['name'],
'path' => $output['path']
);
$response['input'] = array(
'file' => $input['name'],
'path' => $input['path']
);
}
else {
$response['file'] = isset($output) ? $output['name'] : $input['name'];
$response['path'] = isset($output) ? $output['path'] : $input['path'];
}
// Return results as JSON String
Slim::outputJSON($response);
Here is the SLIM.php
<?php
abstract class SlimStatus {
const FAILURE = 'failure';
const SUCCESS = 'success';
}
class Slim {
public static function getImages($inputName = 'slim') {
$values = Slim::getPostData($inputName);
// test for errors
if ($values === false) {
return false;
}
// determine if contains multiple input values, if is singular, put in array
$data = array();
if (!is_array($values)) {
$values = array($values);
}
// handle all posted fields
foreach ($values as $value) {
$inputValue = Slim::parseInput($value);
if ($inputValue) {
array_push($data, $inputValue);
}
}
// return the data collected from the fields
return $data;
}
// $value should be in JSON format
private static function parseInput($value) {
// if no json received, exit, don't handle empty input values.
if (empty($value)) {return null;}
// If magic quotes enabled
if (get_magic_quotes_gpc()) {
$value = stripslashes($value);
}
// The data is posted as a JSON String so to be used it needs to be deserialized first
$data = json_decode($value);
// shortcut
$input = null;
$actions = null;
$output = null;
$meta = null;
if (isset ($data->input)) {
$inputData = null;
if (isset($data->input->image)) {
$inputData = Slim::getBase64Data($data->input->image);
}
else if (isset($data->input->field)) {
$filename = $_FILES[$data->input->field]['tmp_name'];
if ($filename) {
$inputData = file_get_contents($filename);
}
}
$input = array(
'data' => $inputData,
'name' => $data->input->name,
'type' => $data->input->type,
'size' => $data->input->size,
'width' => $data->input->width,
'height' => $data->input->height,
);
}
if (isset($data->output)) {
$outputDate = null;
if (isset($data->output->image)) {
$outputData = Slim::getBase64Data($data->output->image);
}
else if (isset ($data->output->field)) {
$filename = $_FILES[$data->output->field]['tmp_name'];
if ($filename) {
$outputData = file_get_contents($filename);
}
}
$output = array(
'data' => $outputData,
'name' => $data->output->name,
'type' => $data->output->type,
'width' => $data->output->width,
'height' => $data->output->height
);
}
if (isset($data->actions)) {
$actions = array(
'crop' => $data->actions->crop ? array(
'x' => $data->actions->crop->x,
'y' => $data->actions->crop->y,
'width' => $data->actions->crop->width,
'height' => $data->actions->crop->height,
'type' => $data->actions->crop->type
) : null,
'size' => $data->actions->size ? array(
'width' => $data->actions->size->width,
'height' => $data->actions->size->height
) : null,
'rotation' => $data->actions->rotation,
'filters' => $data->actions->filters ? array(
'sharpen' => $data->actions->filters->sharpen
) : null
);
}
if (isset($data->meta)) {
$meta = $data->meta;
}
// We've sanitized the base64data and will now return the clean file object
return array(
'input' => $input,
'output' => $output,
'actions' => $actions,
'meta' => $meta
);
}
// $path should have trailing slash
public static function saveFile($data, $name, $path = 'tmp/', $uid = true) {
// Add trailing slash if omitted
if (substr($path, -1) !== '/') {
$path .= '/';
}
// Test if directory already exists
if(!is_dir($path)){
mkdir($path, 0755, true);
}
// Sanitize characters in file name
$name = Slim::sanitizeFileName($name);
// Let's put a unique id in front of the filename so we don't accidentally overwrite other files
if ($uid) {
$name = uniqid() . '_' . $name;
}
// Add name to path, we need the full path including the name to save the file
$path = $path . $name;
// store the file
Slim::save($data, $path);
// return the files new name and location
return array(
'name' => $name,
'path' => $path
);
}
/**
* Get data from remote URL
* #param $url
* #return string
*/
public static function fetchURL($url, $maxFileSize) {
if (!ini_get('allow_url_fopen')) {
return null;
}
$content = null;
try {
$content = #file_get_contents($url, false, null, 0, $maxFileSize);
} catch(Exception $e) {
return false;
}
return $content;
}
public static function outputJSON($data) {
header('Content-Type: application/json');
echo json_encode($data);
}
/**
* http://stackoverflow.com/a/2021729
* Remove anything which isn't a word, whitespace, number
* or any of the following characters -_~,;[]().
* If you don't need to handle multi-byte characters
* you can use preg_replace rather than mb_ereg_replace
* #param $str
* #return string
*/
public static function sanitizeFileName($str) {
// Basic clean up
$str = preg_replace('([^\w\s\d\-_~,;\[\]\(\).])', '', $str);
// Remove any runs of periods
$str = preg_replace('([\.]{2,})', '', $str);
return $str;
}
/**
* Gets the posted data from the POST or FILES object. If was using Slim to upload it will be in POST (as posted with hidden field) if not enhanced with Slim it'll be in FILES.
* #param $inputName
* #return array|bool
*/
private static function getPostData($inputName) {
$values = array();
if (isset($_POST[$inputName])) {
$values = $_POST[$inputName];
}
else if (isset($_FILES[$inputName])) {
// Slim was not used to upload this file
return false;
}
return $values;
}
/**
* Saves the data to a given location
* #param $data
* #param $path
* #return bool
*/
private static function save($data, $path) {
if (!file_put_contents($path, $data)) {
return false;
}
return true;
}
/**
* Strips the "data:image..." part of the base64 data string so PHP can save the string as a file
* #param $data
* #return string
*/
private static function getBase64Data($data) {
return base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $data));
}
}
That is all the pages includes, I am not sure where to even add this so I can retrieve this rowID, is it under the async, or the slim. Sorry for the confusion. Hopefully adding these pages helped clear some stuff up.
Your HTML can stay the same.
<div class="slim" data-service="async.php" data-ratio="3:2" data-size="600,400">
<input type="file" />
</div>
Append data-meta-data-row to contain the rowID as well in your JS.
(['data-meta-data-row', 'data-row']).forEach( (key) => {
$('.slim').attr(key, rowID);
});
On the server side, you can then use the meta key which holds an object of properties like so:
foreach(Slim::getImages() as $image)
echo $image['meta']->data-row;
So after lots of hacking. I figured it out with the help of the slim frameworks developer.
Per the documentation, there is a function called willSave, this can be triggered and will update whenever is called on the server.
The meta data for slim is only called on page load, that is why it was never reading when the variable was updated via my custom function.
My fix was the following:
After opening the modal, I created the will save function. I passed the variable from the function that opens the modal, to the save function.
Code below for reference and big shout out to the developer for the initial help.
html
<div id="slim" class="slim" data-service="async.php" data-ratio="3:2" data-size="600,400" data-will-save="saveRow">
<input type="file"/>
</div>
JS
function addThumb(rowID) {
//$('.slim').attr('data-meta-data-row', rowID);
window.row = rowID;
$("#imageManager").modal('show');
}
function saveRow(data, ready) {
data.meta.row = window.row;
ready(data);
}

Access variable outside of Excel::load in Laravel

I would like to ask if how can I access the error message variable when I execute the a foreach loop inside the Excel::load function which reads the csv file that I uploaded so that I can return it via the Response::json();
Here's my code:
$errorMessage['error'] = [];
if($request->hasFile('file')){
if($request->file('file')->getClientOriginalExtension() != "csv"){
$errorMessage['error'][] = "File should be in csv format";
}
else {
$fileName = $request->file('file')->getClientOriginalName().".csv";
$destination = base_path().'/storage/excel/imports';
$request->file('file')->move($destination, $fileName);
$csvFile = base_path().'/storage/excel/imports/'.$fileName;
$demographics = $request->get('demographics');
\Excel::load($csvFile, function($reader) use($demographics,$errorMessage) {
if($demographics == "region"){
foreach($reader->get()->toArray() as $data){
$region = Region::whereRaw("LCASE(`short_name`) = ?", array(strtolower($data['region_name'])))->first();
if($region){
$regionData = Region::find($region->id);
$regionData->total_number_of_provinces = $data['total_provinces'];
$regionData->total_number_of_cities_municipalities = $data['total_cities_and_municipalities'];
$regionData->save();
}
else {
$errorMessage['error'][] = $data['region_name'] . " is not existing in the database";
}
}
}
});
}
}
else {
$errorMessage['error'][] = "Please specify a file";
}
return \Response::json($errorMessage);
Bit smelly, but you can declare it a class property.
/**
* #var array
*/
protected $errorMessage;
public function doStuff()
{
// ...
\Excel::load($file, function($reader) use ($demographics) {
// ...
$this->errormessage['error'][] = $data['region_name'];
});
// ...
return \Response::json($this->errorMessage);
}
Note
You can also pass $errorMessage by reference, which a lot of people think is the better choice (you're using a throw-away function after all).
\Excel::load($file, function($reader) use ($demographics, &$errorMessage)
I don't like to do this however, because in my opinion it's less readable what I meant to do. You can choose one of either picks though!
Useful and short explanation: http://culttt.com/2013/03/25/what-are-php-lambdas-and-closures/
$fileName = md5(time()) .'.'.$request->file('file')->getClientOriginalExtension();
$sheet_id = $request->session()->get('sheet_id');
$excel=Excel::load(public_path('/uploads/importsheet/'.$fileName),function ($reader)use ($sheet_id) {
$reader->each(function($sheet) use ($sheet_id) {
$headings = $sheet->keys()->toArray();
for($i=0; $i<count($headings); $i++){
$sheet_id = DB::table('import_sheets_attributes')->insertGetId(
[
'import_sheets_id' => $sheet_id,
'attribute' => $headings[$i],
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s')
]);
}
});
});
Hope the above sample code will help.

Categories