PHP how to send array variables to Class function - php

I'm writing a code in PHP OOP and I'm trying to send $_POST data
filtered by one Class function to another Class function that will add
the data to database. Specifically login and password in registration
form.
I have 3 Classes that will do that:
Is simple Class that handles connection to database (I think it is not necessary to put code here)
Is the Class that filters the coming $_POST-s:
class Filter extends Dbconnect {
protected $login;
protected $haslo;
public function regFilter() {
if (isset($_POST))
{
foreach($_POST as $key => $val)
{
$filterVal = strip_tags($val);
$filterVal = htmlspecialchars($filterVal);
$filterVal = stripslashes($filterVal);
$filterVal = str_replace("\\", "", $filterVal);
$filter = array(
$key => $filterVal
);
foreach($filter as $key => $val)
{
echo "[$$key]";
echo "$val";
$
{
$key
} = $val;
}
}
return $filter = array(
'login' => $login,
'haslo' => $haslo
);
}
else
{
echo "Proszę podać login i hasło!";
}
}
}
Class that will get login and password and send it to DB:
class Dbinsert extends regFilter{
//protected $login;
//protected $haslo;
protected $query;
protected $dbo;
public function insert(){
//$this->extract = extract($filter);
//$this->login = $login;
//$this->haslo = $haslo;
$this->connect();
$this->query = "INSERT INTO uzytkownik (id, nazwa, haslo) VALUES ('', :login, OLD_PASSWORD(:haslo))";
if(!$result = $this->connect()->prepare($this->query)){
echo 'Zapytanie nie powiodło się';
}
else{
$result->bindParam(':login', $login);
$result->bindParam(':haslo', $haslo);
$login = $_POST['login'];
$haslo = $_POST['haslo'];
$result->execute();
}
$dbo = null;
}
}
Now when I try to send data from form with objects:
$rejestruj = new Dbinsert();
$filtruj = $rejestruj->regFilter();
var_dump($filtruj);
$dodaj = $filtruj->insert();
I get the following result:
[$login]login
[$haslo]password123
array(2) { ["login"]= string(5) "login" ["haslo"]= string(11) "password123" }
Fatal error: Call to a member function insert() on array in `E:\Xampp\htdocs\php\bazy_danych\obiektowe\my\register.php` on line 78
Which doesn't surprises me since: login and haslo is returned from
"foreach" loop in class Filter (which is just for testing) "array(2)"
is returned from "var_dump($filtruj);"(to check if it is actually
working) and error is returned since I send an array to Class
Dbinsert - but in the function I put "extract" to get the variables.
How can I send just the variables from this filtered array to class
Dbinsert?
Edit: As #Twinfriends suggested I corrected function insert in class Dbinsert to actually use prepared statement, thats why (for now) login and haslo variables are reffering to $_POST. Now I need answer to my question.
(First time posting, thanks for edit suggestions, also any advice is appreciated since I'm quite the beginner
in PHP)

Sorry that it took so long to answer, I totally forgot your question. Well, lets take a look at your problem, hope to solve it.
I try to explain it as good as I can, so that you understand whats going on. First of all, lets look at your error message
Fatal error: Call to a member function insert() on array in
E:\Xampp\htdocs\php\bazy_danych\obiektowe\my\register.php on line 78
Okay. Call to a function on array... lets have a look at how you actually call the function:
$rejestruj = new Dbinsert();
$filtruj = $rejestruj->regFilter();
var_dump($filtruj);
$dodaj = $filtruj->insert();
And exactly here is your error. You have to understand that you call methods on objects and pass your data to this methods, not to call the methods on your data. What do I mean with that?
$rejestruj is your Dbinsert object. You create it in your first line of code here. Then, you call the regFilter function on it. Still anything is fine. As you see, var_dump gives you the expected results. So the error has to be on your last lane of code. And indeed, you try to call the method insert() on your array. And that won't work, since your array don't know any method called insert().
The right call to the method would be (Not the final one!!!):
$dodaj = $rejestruj->insert();
Now the method call should work. But in fact, it won't insert anything. Why? Because your insert() method try to bind the variables $login and $haslo - two variables the method don't know. So we need to pass the data in your method. To do that, you have to do the following changes:
Method call:
$rejestruj->insert($filtruj); // $filtruj contains your array
And your Dbinsert should look like:
class Dbinsert extends Dbconnect{
protected $query;
protected $dbo;
public function insert($data){
$this->connect();
$this->query = "INSERT INTO uzytkownik (id, nazwa, haslo) VALUES ('', :login, OLD_PASSWORD(:haslo))";
if(!$result = $this->connect()->prepare($this->query)){
echo 'Zapytanie nie powiodło się';
}
else {
$result->bindParam(':login', $data["login"]);
$result->bindParam(':haslo', $data["haslo"]);
$result->execute();
}
$dbo = null;
}
}
I hope your code works with this changes. So, while in my opinion the code should work now, I want to mention that there are many things you could improve. For example, you're not programming real "object-oriented" ... its more some pseudo OOP you're writing here. Some things are quite bad practice (could be done much easier). I don't want to dive to deep into details, since I don't know if you're interested in it. If you wish I can give you some more advises, but only if you wish.
Otherwise I really hope my answer help you. If the whole thing still doesn't work, please let me know so I can look at it again.
Have a nice day ;)
Edit:
Since it seems I haven't been clear enough, here the code how it should look like now:
$rejestruj = new Dbinsert();
$filtruj = $rejestruj->regFilter();
$dodaj = $rejestruj->insert($filtruj);

Related

Calling methods on object gets 'call to member function on array' error

I inherited this project from my predecessor, and he was way overqualified. A lot of stuff he wrote goes over my head. But as far as vanilla php goes, I'm pretty confident, and can't for the life of me figure out why the application thinks the object I created is an array. Maybe I don't actually know anything. You tell me.
use via\zoom\Bulletin;
use via\zoom\DatabaseConnection;
require_once('includes/config.php');
require_once(CORE .'sql.php');
require_once(CORE . 'model.php');
require_once(CORE . 'bulletin.php');
// If we've passed the validation step we can guarantee we have a valid $active_user
validate();
//run if a page deletion has been requested
if (isset($_GET['delpage'])) {
$del = $_GET['delpage'];
$bulletin = new Bulletin;
$bulletin = Bulletin::get($del);
if(!empty($bulletin))
{
$bulletin->delete();
/*
So.
For some reason, the above object is cast as an array.
If you try to cast it as an object, it defaults to stdClass.
On the left we have a method complaining that it can't work outside of its class. Hard stop, array to method exception.
On the right we have an object with all the right data, but set to the wrong class, so it can't find the delete method at all. Hard stop, undefined method exception.
*/
//this is the workaround, pulled the script straight from the delete method in the model class
/*$dbh = DatabaseConnection::get();
$query_string = "DELETE FROM brochure_generator_bulletin WHERE id = $del";
try {
$dbh->query($query_string);
//return true;
} catch (\Exception $e) {
//return false;
}*/
}
header('Location: bulletins');
exit();
}
Here's the get method from the Bulletin class, extends Model--
public static function get( ...$ids )
{
$matches = parent::get( ...$ids );
foreach( $matches as &$match )
{
$match->content = json_decode( $match->content );
}
return $matches;
}
And here's the delete method from the Model Class:
public function delete()
{
if (isset($this->id)) {
$dbh = DatabaseConnection::get();
$query_string = "DELETE FROM {$this->table_name} WHERE id = \"{$this->id}\"";
try {
$dbh->query($query_string);
return true;
} catch (\Exception $e) {
return false;
}
}
return false;
}
What am I missing? Is he using a framework I'm not familiar with? I'm utterly grasping at straws here, and at this point my options are grab all the method scripts and stick them where they need to be inline, or just starting over from the ground up.
You don't need to create a new Bulletin object before using the static get() method, so you can remove this:
$bulletin = new Bulletin;
That $bulletin variable is immediately overwritten by the next line anyway.
$bulletin = Bulletin::get($del);
get() takes one or more ids and returns an array of one or more corresponding objects. You're giving it one id and expecting one object back, but it's still going to return that object inside an array. You just need to get the object out of the array so you can call its delete method.
if(!empty($bulletin))
{
$bulletin = reset($bulletin); // get the first item in the array
$bulletin->delete();
You could also review the model and see if it has a different method that returns a single object rather than an array of objects.

Pass an array to Redirect::action in laravel

I'm trying to pass an array from a function to another function in laravel.
In my PageController.php, I have
public function show($code, $id){
//some code
if(isset($search))
dd($search);
}
and another function
public function search($code, $id){
//some queries
$result = DB::table('abd')->get();
return Redirect::action('PageController#show, ['search'=>$search]);
}
But this returns me an error like this: ErrorException (E_UNKNOWN)
Array to string conversion
I'm using laravel.
You could maybe get it to work with passing by the URL by serialization, but I'd rather store it in a session variable. The session class has this nice method called flash which will keep the variable for the next request and then automatically remove it.
Also, and that's just a guess, you probably need to use the index action for that, since show needs the id of a specific resource.
public function search($code, $id){
//some queries
$result = DB::table('abd')->get();
Session::flash('search', $search); // or rather $result?
return Redirect::action('PageController#index');
}
public function index($code){
//some code
if(Session::has('search')){
$search = Session::get('search');
dd($search);
}
}

PHP My SQL Error Strict standards: Resource ID#11 used as offset, casting to integer (11)

my Code
function db_fetch_array($query_id = '')
{
if(!$query_id)
{
$query_id = $this->query_result;
}
if($query_id)
{
// success
$this->row[$query_id] = mysql_fetch_array($query_id);
return $this->row[$query_id];
}
else
{
// failure
return false;
}
}
for starters i would do something like this:
if (empty($query_id))
instead of
if (!$query_id)
since !$query_id does not check for empty strings
Further, the error seems to be an issue with using the $query_id as an array key. You may need to find a different identifier
as per divaka's potential alternative in comments below:
Use something else for a key. You can fetch the result first, then get the id of the row and apply it as a key in you array
In case you want to stack several database connections,
consider linking the database in the constructor and instanciate several of these classes, which you can hold in an array.
Example:
class Database
{
protected $link;
public function __construct($user, $pass, $host) {
$this->link = new Mysqli(/* ... */);
}
public function fetch($query) {
$stmt = $this->link->prepare($query);
/* ... */
}
/* ... */
}
Now have your databases in an array:
$db[0] = new Database('root', 'root', 'server1');
$db[1] = new Database('root', 'root', 'server2');
$db['bigCluster'] = new Database('user01', 'passwd', 'cluster.your.biz');
$result = $db[0]->fetch("SELECT * FROM table");
This way you have way better access, control and debugging is easier.
To say something about your code:
function db_fetch_array($query_id = '') { /* .... */ }
This function accepts an empty parameter, thus, allowing the user to fetch from a non-existent database connection. Which results in an error. Don't allow it!
Even better, typehint it:
public function db_fetch_array(\Mysqli $query_id) { /* .... */ }
Solves all your problems at once!
If you need an it your way tho, try the following, giving you a unique, printable id to use as an array key:
$query_id = md5((string)$query_id);
Have a look at the Zend code style guide and modern PHP design patterns, this will help you to increase your code quality by a few hundred percent.

What is correct syntax for calling a function recursively in php

I have a function which is using recursion to call itself and I need to know the correct syntax for calling itself.
Note: I am using Object oriented programming technique and the function is coming from a class file.
Below is my function
// Generate Unique Activation Code
//*********************************************************************************
public function generateUniqueActivationCode()
{
$mysql = new Mysql();
$string = new String();
$activation_code = $string->generateActivationCode();
// Is Activation Code Unique Check
$sql = "SELECT activation_id FROM ". TABLE_ACTIVATION_CODES ." WHERE activation_code='$activation_code' LIMIT 1";
$query = $mysql->query($sql);
if($mysql->rowCount($query) > 0)
{
// This function is calling itself recursively
return generateUniqueActivationCode(); // <- Is this syntax correct in Oops
}
else
{
return $activation_code;
}
}
Should the code to call it recursively be
return generateUniqueActivationCode();
OR
return $this->generateUniqueActivationCode();
or if something else other than these 2 ways.
Please let me know.
You would need to call it with the $this variable since your function is part of the instance. So:
return $this->generateUniqueActivationCode();
PS: Why not just try both methods and see if it generates any errors?
Recursion is the COMPLETELY WRONG WAY TO SOLVE THIS PROBLEM
Unlike iteration you're filling up the stack, and generating new objects needlessly.
The right way to solve the problem is to generate a random value within a scope which makes duplicates very unlikely, however without some external quantifier (such as a username) to define the scope then iteration is the way to go.
There are further issues with your code - really you should be adding records in the same place where you check for records.
I am using Object oriented programming technique and the function is coming from a class file
Then it's not a function, it's a method.
And your code is susceptibale to SQL injection.
A better solution would be:
class xxxx {
....
public function generateUniqueActivationCode($id)
{
if (!$this->mysql) $this->mysql = new Mysql();
if (!$this->string) $this->string = new String();
$limit=10;
do {
$activation_code = $string->generateActivationCode();
$ins=mysql_escape_string($activation_code);
$sql="INSERT INTO ". TABLE_ACTIVATION_CODES ." (activation_id, activation_code)"
. "VALUES ($id, '$ins)";
$query = $mysql->query($sql);
if (stristr($query->error(), 'duplicate')) {
continue;
}
return $query->error() ? false : $activation_code;
} while (limit--);
return false;
}
} // end class

Accessing array in class structure

I want to validate a form with php.
Therefor I created a class "benutzer" and a public function "benutzerEintragen" of this class to validate the form:
class benutzer
{
private $username = "";
private $mail = "";
private $mail_check = "";
private $passwort = "";
private $passwort_check = "";
public $error_blank = array();
public $error_notSelected = array();
public $error_notEqual = array();
public function benutzerEintragen () {
$textfields[0] = $this->username;
$textfields[1] = $this->mail;
$textfields[2] = $this->mail_check;
$textfields[3] = $this->passwort;
$textfields[4] = $this->passwort_check;
foreach ($textfields as $string) {
$result = checkFormular::emptyVariable($string);
$error_blank[] = $result;
}
In the function "benutzerEintragen" i filled the variables "username,mail" and so on with the appropriate $_POST entries (not shown in the code above). The call
checkFormular::emptyVariable($string)
just returns "TRUE" if the field is not set or empty otherwise FALSE.
Now when i try to create a new instance of this class, execute the function and get access to $error_blank[0] the array is empty!
if (($_SERVER['REQUEST_METHOD'] == 'POST')){
$BENUTZER = new benutzer();
$BENUTZER->benutzerEintragen();
echo $BENUTZER->error_blank[0];}
So the last line is leading to a "Notice: Undefined offset: 0". It seems to be related to the array structure, because if i do
echo $BENUTZER->mail;
I get any input I wrote in the form, which is correct. Also the foreach loop seems to do the right thing when i run the debugger in phpEd, but it seems like the array "error_blank" is erased after the function is executed.
Any help would be greatly appreciated. Thanks in advance.
There is a scope problem here. You do have a class attribute with the name. Unlike in Java where using a local variable with the same name as a class variable automatically selects the class attribute this is not the case in PHP.
Basically you are saving your output in a local variable which gets discarded once you leave the function. Change $error_blank[] = $result; to $this->error_blank[] = $result; and you should be fine.
First of all this seems overly complicated way to do a simple task, but that wasn't actually the question.
You are creating a new $error_blank variable that is only in function scope. If you wish to use the class variable you should use $this->error_blank[]

Categories