php class not executing else statement - php

Being a noob ... I can't quite figure out what isn't working here ....
if the file is empty, $this->result contains the right error message.
But if I have a file name, the result array is empty and I'm not getting an upload
class upload_f
{
public $path; // path to upload from root ie files/images/
public $fileName; // current file ie $_FILES['uploadedfile']['name'];
public $result = array(); // array containing error to be loop outside object
public function validateInput() // verify is minimal data is entered.
{
if (empty($this->fileName))
{
$this->result[] = "ERROR: File name is empty.";
return false;
}
} // end of validate
public function upload()
{
// run validation
if (!$this->validateInput())
{
return $this->result;
}
else
{
$f_name = $this->fileName;
$path_fileName = $this->path.$this->fileName;
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $path_fileName))
{
$this->result[] =
"File ". basename( $_FILES['uploadedfile']['name']). " was uploaded";
}
else
{
$this->result[] = "There was an error uploading the file, please try again!";
}
$this->result[] = $path_fileName;
return $this->result;
} // end of else : upload execution if no errors
}
} // end of upload class
[...]
//****************************************/
// call the object
// form here with a if - post ...
$the_array = $test->upload();
$test = new upload_f();
// assgin values
$test->path = "docs/";
$test->fileName = $_FILES['uploadedfile']['name'];
$the_array = $test->upload();
echo "<pre>";
print_r ($the_array);
echo "</pre>";

You should change validateInput() to:
public function validateInput() {
if (empty($this->fileName)) {
$this->result[] = "ERROR: File name is empty.";
return false;
}
return true; // <-- return true if input is valid
}
As you have it, the method returns something falsy for all cases, causing !$this->validateInput() always to evaluate to true.
Reference
Converting to boolean

Not sure if it's your problem, but you're missing a closing brace at the end of your upload class.
I noticed looking at your code that you have an odd style of using curly braces. It would be great to get in the habit of picking a style and sticking with it. You can use any style, as long as it's consistent. Here's a list of them: Indent Styles

Related

Variable to another php file

I have a php file(register.php) with a public function register($data) where errors are validated.Then errors are counted and if no errors are found, validation is passed.
register.php:
class ARegister {
public function register($data) {
$user = $data['userData'];
//validate provided data
$errors = $this->validateUser($data);
if(count($errors) == 0) {
//first validation
}
}
public function validateUser($data, $botProtection = true) {
$id = $data['fieldId'];
$user = $data['userData'];
$errors = array();
$validator = new AValidator();
if( $validator->isEmpty($user['password']) )
$errors[] = array(
"id" => $id['password'],
"msg" => Lang::get('password_required')
);
return $errors;
}
The problem is, that I need to get this confirmation of validated data to my other php file (othervalidation.php) where I've made another validation:
othervalidation.php:
<?php
require 'register.php';
if ( !empty($action) ) {
switch ( $action ) {
case 'process_payment':
try {
$instance = new ARegister();
if($instance->validateUser($data, $errors)) {
throw new Exception('Validation error');
}
} catch (Exception $e) {
$status = false;
$message = $e->getMessage();
}
}
How can I send the result of $errors variable to my other validation (othervalidation.php)?
I looked at your new code design and here's the new problems I found.
First, in your register function, you use the errors variable as an integer while your validate function returns an array. You got two possibilities here.
You can change your register method to check out if your error array is empty like this:
if(empty($errors)) {
//first validation
}
Count is also valid, but I still prefer empty since it's syntactically clearer. Furthermore, the count function returns 1 if the parameter is not an array or a countable object or 0 if the parameter is NULL. As I said, it is a functional solution in your current case but, in some other contexts, it might cause you unexpected results.
Here in your method declaration, I see that you are expecting a boolean (botProtection).
public function validateUser($data, $botProtection = true) {
But you are supplying an errors parameter
if($instance->validateUser($data, $errors)) {
You don't provide me the declaration of the errors variable, but it is probably not matching the bot protection parameter your function is expecting. PHP is using lose typing, it is useful but, once again, you got to be careful for bugs hard to find. For public function, you should always make sure a way or another that the supplied parameter won't lead to code crash.
In your code, the data parameter seems to be an array. You can use parameter hinting to force the use of array like this:
public function register(array $data) {
public function validateUser(array $data, $botProtection = true) {
And even specific class (as if you where using "instance of" in a condition)
public function register(MyDataClass $data) {
public function validateUser(MyDataClass $data, $botProtection = true) {
Also, you're not even using the botProtection parameter in your validateUser method.
On the same function call:
if($instance->validateUser($data, $errors)) {
you are expecting a Boolean (true or false), but the method returns an array. If you want to use the code the way it is currently designed, you must use it like this
if(!empty($instance->validateUser($data, $errors)) {
Here, I'm not so sure it is necessary to use exception. Ain't it be easier to design your code like this?
if(!empty($instance->validateUser($data, $errors)) {
$message = 'Validation error';
}
In your validate function, is the "isEmpty" function also validating if the client provided a password?
If that's the case you could validate it like this:
if(!in_array($user['password']) or empty($user['password']))
With those corrections, your code should be functional.
Here's a sample of how I would had design your code (considering the code sample provided):
class ARegister {
public function register($data) {
$user = $data['userData']; //don't declare it here, all the user validations must be done in validateUser($data, &$errors)
$errors = array();
if($this->validateUser($data, $errors)) {
//first validation
}
}
/**
* Note: If you are not returing more than one error at the time, $errors should be a string instead of an array.
*/
public function validateUser($data, array &$errors) {
$isValid = false;
if (in_array($data['fieldId']) and in_array($data['fieldId']['password']) and in_array($data['userData'])){
if(!in_array($data['userData']['password']) or empty($data['userData']['password'])){
$errors[$data['fieldId']['password']] = Lang::get('password_required');
}
else{
$isValid = true;
}
}
else{
//an invalid data array had been provided
}
return $isValid;
}
For the next part, if the code is executed directly in the view and you are a beginner, create a procedural external controller file (all functions will be public...). If you are a professional, you MUST create a class to encapsulate the treatment.
You must not do treatment directly in the view. The view is a dumb placeholder for data presentation and collecting client's input. The sole action it must do is display the data sent by the controller and send back the client's input to the controller.
The treatment on data is the controller responsibility.
if (!empty($action) ) {
$errors =array();
switch ( $action ) {
case 'process_payment':
$instance = new ARegister();
if($instance->validateUser($data, $errors)) {
//the user is valid, do the treatment
}
else
PageManager::dispayError($errors);
}
unset($instance);
}
}
Here's an example how you can centralize your error display
/**
* Can be more complexe than that, but I'm at my father's home at four hundred kms away from Montreal right now..
*/
public static function dispayError($errors, $size = 4){
if (is_numeric($size)){
if ($size < 0){
$size = 1;
}
elseif($size > 5){
$size = 5;
}
}
else{
$size = 4;
}
if (is_scalar($errors)){
echo '<h' . $size . 'class="ERROR_MESSAGE">' . $errors . '</h' . $size . '><br>';
}
elseif (is_array($errors)){
foreach ($errors as $error){
if (is_scalar($error)){
echo '<h' . $size . 'class="ERROR_MESSAGE">' . $error . '</h' . $size . '><br>';
}
}
}
}
Of course, you can also support many kind of message:
public static function dispayError($errors, $size = 4){
self::displayMessage("ERROR_MESSAGE", $errors, $size=4);
}
private static displayMessage($class, $messages, $size=4)
Well, took me two hours to write that. I hope you have now enough material to build an efficient, reusable and, no less important, safe code design.
Good success,
Jonathan Parent-Lévesque from Montreal
You can try something like this:
class ARegister {
private $error = 0;
public function register($data) {
if (!$this->validateUser($data)){
$this->error++;
}
}
public function getErrorCount(){
return $this->error;
}
public resetErrorCount(){
$this->error = 0;
}
Or pass the error by reference:
public function register(&$error, $data) {
if (!$this->validateUser($data)){
$error++;
}
}
Personally, I would do all the validation in the same method (in the class for encapsulation), use an error message parameter (passed by reference) to return why the validation failed and use the return statement to return true or false.
class MyClass{
public function validation(&$errorMessage, $firstParameter, $secondParameter){
$success = false;
if (!$this->firstValidation($firstParameter)){
$errorMessage = "this is not working pal.";
}
elseif (!this->secondeValidation($firstParameter)){
$errorMessage = "Still not working buddy...";
}
else{
$success = true;
}
return $success;
}
private function firstValidation($firstParameter){
$success = false;
return $success;
}
private function secondeValidation($secondParameter){
$success = false;
return $success;
}
}
In your other file:
<?php
$instance = new MyClass();
$errorMessage = "";
if ($instance->validation($errorMessage, $firstParameter, $secondParameter)){
echo "Woot, it's working!!!";
}
else{
echo $errorMessage;
}
?>
Is one of these code solutions fit your needs?
Jonathan Parent-Lévesque from Montreal

Class constructor error on validation

I am developing a file uploaded class, and trying to perform few validation before other codes, but its returning all vars instead of false, check following code....
class FileUploader
{
private $filePath;
function __construct($file_path) {
if(file_exists($file_path)) {
$this->filePath = $file_path;
}
else return false;
}
}
When I am using this class like following....
$file_path = getcwd().'\img.pn'; //invalid path
$file_uploader = new FileUploader($file_path);
if($file_uploader) {
//process
}
else {
echo 'Invalid File Path!';
}
But it doesn't echo Invalid File Path as expected, when i tried var_dump, it returned following output...
object(FileUploader)[1]
private 'filePath' => null
Please help to fix this. thanks.
You might consider using an exception in the constructor as constructors should no return anything. (Have a look at this question).
Otherwise you may create a function to check the file_path :
class FileUploader
{
private $filePath;
function __construct($file_path) {
$this->filePath = $file_path;
}
function isValidFilePath() {
return file_exists($this->file_path);
}
}
and then :
$file_path = getcwd().'\img.pn'; //invalid path
$file_uploader = new FileUploader($file_path);
if($file_uploader->isValidFilePath()) {
//process
}
else {
echo 'Invalid File Path!';
}

How to save file to server after checking for validation with PHP

If a user uploads a file and the contents are retrieved like so
$file = $_FILES['uploadedFile'];
Then, the file is sent to a function to make sure it's an accepted file type. If it is, save it on the server
function saveInputFile($file){
if($check->checkFile($file)== TRUE){
//save $file on my server
}
else{
echo "can't be saved!";
}
}
Assuming it passes the checkFile function, how can I then save this file to my server from within the saveInputFile function? Can I set the file equal to a variable, and then save that variable or do I have to save the file directly from the POST data?
I've seen it done like this, but I already have the file passed into this function.
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
echo "The file ". basename( $_FILES['uploadedfile']['name']). " has been uploaded";
} else{
echo "There was an error uploading the file, please try again!";
}
When it comes down to it, I want to save a file in the following function. Can I pass the file like a variable as I did in the saveInputFile function above, or does it not work like this?
You can make the upload file a type of it's own that has the methods it needs next to it's data. That will make the usage more flexible:
$upload = new UploadFile($_FILES['uploadedFile']);
$message = saveInputFile($upload);
echo $message;
function saveInputFile(UploadFile $upload)
{
if ($check->checkFile($upload->getBasename()) == TRUE) {
$message = $upload->moveTo($target_path)
? sprintf('The file %s has been uploaded', $upload->getBasename())
: 'There was an error uploading the file, please try again!'
;
} else {
$message = "can't be saved!";
}
return $message;
}
The new type UploadFile represents one file from the the $_FILE array, it is a class that wraps the basic data and methods a file-upload carries. Here is some example code:
class UploadFile
{
protected $file;
private $filename;
public function __construct(array $file)
{
$this->file = $file;
}
public function hasError()
{
return $this->getProperty('error') !== UPLOAD_ERR_OK;
}
public function getError()
{
return $this->getProperty('error');
}
public function getBasename()
{
return basename($this->getProperty('name'));
}
public function getFilename()
{
return $this->filename;
}
/**
* #param $newName
* #return NULL|SplFileInfo
* #throws BadMethodCallException
*/
public function moveTo($newName)
{
$newName = (string)$newName;
$filename = $this->getFilename();
if ($filename !== NULL) {
throw new BadMethodCallException(sprintf('Upload file (%s) has been already moved (%s).', $this->getBasename(), $filename));
}
$tmpName = $this->getProperty('tmp_name');
if (move_uploaded_file($tmpName, $newName)) {
$this->filename = realpath($newName);
}
return $this->getFileInfo();
}
/**
* #return SplFileInfo|NULL
*/
public function getFileInfo()
{
$filename = $this->getFilename();
if ($filename !== NULL) {
return new SplFileInfo($filename);
}
}
protected function getProperty($name, $default = NULL)
{
if (isset($this->file[$name])) {
return $this->file[$name];
}
return $default;
}
}
Use it at your will. See as well SplFileInfo and the documentation about file uploads in the PHP manual which documents the structure of the $_FILE array and the PHP upload error codes (which are important).
Your move_uploaded_file function should take 2 parameters, the source file name and the destination file name.
In PHP the file move function is called rename.

returning boolean on class method

I have a class with a couple of methods
deleteUploadedFile() and currentUploadedFiles().
currentUploadedFiles(), basically loops over a session array and displays it on screen, simple as. Code sample:
function currentUploadedFiles()
{
if(isset($_SESSION['fileArray']) && $this->count > 0)
{
echo '<p style="clear:both">Current files uploaded list:</p>';
echo '<ol>';
foreach($_SESSION['fileListing'] as $key => $value )
{
echo '<li>'. $value .' [Remove File]</li>';
}
echo "</ol>\n\r";
echo "<p> Current file size allowance: ". $this->_returnRemainingSessionFileSize() ." of 8 MB";
} else {
echo '<p style="clear:both">No files have been uploaded yet</p>';
}
if($this->deleteUploadedFile() === true)
{
echo '<p>File has now been deleted from our records.</p>';
}
}
the deleteUploadedFile() method, basically when form is submitted it deletes file from the server and removes the entry from the session array. Sample code:
function deleteUploadedFile()
{
(int) $id = $_GET['id'];
(bool) $deleted = false;
if (file_exists($this->target_path.'/'.$_SESSION['fileArray'][$id]))
{
$_SESSION['fileSize'] -= $this->_checkSessionFileSize($id);
if (unlink($this->target_path.'/'.$_SESSION['fileArray'][$id]))
{
$deleted = true; //'<p>File has now been deleted from our records.</p>';
unset($_SESSION['fileArray'][$id]);
unset($_SESSION['fileListing'][$id]);
}
}
return $deleted;
}
my controller, basically checks if file id# isset, then checks if the array id# isset, then calls the deleteUploadedFile() method and then calls the currentUploadedFiles() method.
Question is, why when I var_dump $deleted var in deleteUploadedFile() I get bool(true) but inside the currentUploadedFiles() method I get bool(false). Sounds like I'm messing up the scope somehow?
Looks like $deleted is in the local scope of the delete function.
Something like the following should work.
class theClass
{
function __construct()
{
$this->deleted = false
}
function delete()
{
$this->deleted = true;
}
function upload()
{
var_dump($this->deleted);
}
}

PHP: How to implement exif_imagetype in this code

Please take a look at this: http://phpbin.net/x/1841090478
Now I am trying to expand this code and add more checkers, like exif_imagetype() as you can see on line 139.
I cant get it to work, Im just receiving that exif_imagetype failed to open stream, no such... ( that the image doesnt exists ). I also tried $this->file->getName() inside the parameter, but still the same error.
Now I am questioning the whole thing. I cant see anywhere the image gets uploaded before it gets to the if($this->file->save .. but how can it retrieve pathinfo() then? And why wont ['dirname'].['basename'] to find the file not work? for the dirname i just get a . but the basename i get the correct image file name i am trying to upload.
So how does it work and where should i implement this exif_imagetype checker into this code?
Thank you in forward.
Just a quick and dirty implementation for the XHR case (as discussed in the chat):
/**
* Handle file uploads via XMLHttpRequest
*/
class qqUploadedFileXhr {
protected $_tempFile;
public function __construct() {
$input = fopen("php://input", "r");
$this->_tempFile = tempnam(sys_get_temp_dir(), 'xhr_upload_');
file_put_contents($this->_tempFile, $input);
fclose($input);
}
public function checkImageType() {
switch(exif_imagetype( $this->_tempFile )) {
case IMAGETYPE_GIF:
case IMAGETYPE_JPEG:
case IMAGETYPE_PNG:
return true;
break;
default:
return false;
break;
}
}
/**
* Save the file to the specified path
* #return boolean TRUE on success
*/
function save($path) {
if (filesize($this->_tempFile) != $this->getSize()){
return false;
}
rename($this->_tempFile, $path);
return true;
}
function getName() {
return $_GET['qqfile'];
}
function getSize() {
if (isset($_SERVER["CONTENT_LENGTH"])){
return (int)$_SERVER["CONTENT_LENGTH"];
} else {
throw new Exception('Getting content length is not supported.');
}
}
}

Categories