I currently have the following code in a ZF application, to set the values of a Form based on a rowset retrieved from a Db-Table.
$form->forename->setValue($footerContactDetails->forename);
$form->surname->setValue($footerContactDetails->surname);
$form->telephone->setValue($footerContactDetails->telephone);
$form->mobile->setValue($footerContactDetails->mobile);
$form->fax->setValue($footerContactDetails->fax);
$form->email->setValue($footerContactDetails->emailAddress);
$form->address1->setValue($footerContactDetails->address1);
$form->address2->setValue($footerContactDetails->address2);
$form->address3->setValue($footerContactDetails->address3);
$form->townCity->setValue($footerContactDetails->townCity);
$form->region->setValue($footerContactDetails->region);
As the object element names from the rowset match the form elements, what I'd like to do is the following:
foreach ($footerContactDetails as $key=>$value) {
$form->$key->setValue($value);
}
However this provides the following error message:
Fatal error: Call to a member function setValue() on a non-object
I expect this question is more related to OOP PHP in general and not the just ZF.
So how can I set these form values using a foreach?
Many thanks
The foreach is fine, but the names dont match:
$form->email->setValue($footerContactDetails->emailAddress);
So, when iterating over $footerContactDetails, your code will eventually try to
$form->emailAddress->setValue()
but since there is no element of that name in the Zend_Form (it's called email instead), you'll get the error. So change it accordingly and it will work.
On a sidenote, Zend_Form has a method for bulk setting:
$form->populate((array) $footerContactDetails);
It expects an array though, hence the typecast.
Try this:
foreach($footerContactDetails as $key=>$value){
$form->{$key}->setValue($value);
}
Foreach over object variables takes all variables. That means primitive types too. Since primitive type is not an object, you cannot call method on it.
I suggest you use is_object() to check if variable is an object before calling a method, or maybe even think of a different approach.
Did you try something like this?
foreach ($footerContactDetails as $key=>$value) {
$form->${$key}->setValue($value);
}
Related
Let me explain myself.
function insertObjects($objs) {
foreach ($objs as $obj) {
$this->repository->insert($obj);
}
}
I don't want to test that insertion into the database worked because I assume it works (it's a different unit). I also don't want to test foreach because obviously foreach is going to work. So the only thing to test here is that $objs is a well formed array. But if $objs is the mock data that I will be passing in... so does this mean there is nothing to test for this function?
If there's any chance of invalid input (a not well-formed array, null value, etc.), you need to handle that case in your method by explicitly checking for it.
In your test, you would then try to call your method with various invalid values, and check whether your method responds correctly, i.e. the database insert method is not called, exceptions are thrown, errors are logged, etc.
Other than that, the only thing to test is whether your database insert method is called with the parameters that correspond to the values in the valid test array you pass in.
I've been using procedural php for a long time but am still learning OOP. I was able to find a bit of code online that is in the form of a class and I am able to call a new instance of the class and use var_dump on a string to have it print JSON data to a web page. I can look at the results of the var_dump and see that it's returning exactly what I want. I'm then able to use json_decode on the same string to turn it into and associative array and then I can echo the values from within the class. The problem is, I need to use the array values in more code - it's great that I can confirm it by printing it to a web page but I need to use it... but I'm getting errors that state the array is undefined once I try to access it outside of the class.
I'm using this line to convert the data into an array:
$response_array = json_decode($body, true);
I've already confirmed that this works within the class by using this code to print some of the data:
echo $response_array['amount'];
and it works - I see it on the web page.
I've been using this code to create the new instance of the class:
$fdata = new FData();
$fdata->request($order_total, $cc_exp, $cc_number, $cc_name, $order_id, $customer_id);
(the function named 'request' is defined as a public function inside the class)
After that, I want to grab the $response_array so that I can store the returned data into a transactions table, i.e something like this:
$r = mysqli_query($dbc, "CALL add_transaction($order_id, $response_array['transaction_type'], $response_array['amount'], $response_array['exact_resp_code'], $response_array['exact_message'], $response_array['bank_resp_code'], $response_array['bank_message'], $response_array['sequence_no'], $response_array['retrieval_ref_no'], $response_array['transaction_tag'], $response_array['authorization_num'])");
but I keep getting an error saying that the array values are undefined.
Things I have already tried (and which failed) include:
Defining the variables as public inside the class, setting their value in the class, and then calling them outside the class...
public $amount = $response_array['amount'];
then using $amount in my procedure CALL --- I still get the error saying that $amount is undefined.
Using 'return', as in
return $response_array;
and still the error saying the values are undefined.
I tried embedding the entire rest of my code within the class, just copy/paste it in right after the json_decode... but for some reason it can't seem to then make the database calls and other things it needs to do.
I've been reading about __construct but I'm not sure if it applies or how to use it in this case...
I want to stress that I AM able to see the results I want when I use var_dump and echo from within the class.. I need to access the array created by json_decode OUTSIDE of the instance of the class.
Any advice would be greatly appreciated. Thanks.
Assuming your FData::request method ends with something like this...
$response_array = json_decode($body, true);
return $response_array;
and you call it like this...
$response_array = $fdata->request(...);
You should then be able to use $response_array in the calling scope.
Extra note; you should be using prepared statements with parameter binding instead of injecting values directly into your SQL statements.
This is probably very easy to do, but I can't seem to get my head around it right now. Let's say in a component in a cakephp application, I have a variable my_model, which contains the model of the corresponding controller that is currently using the component like:
function TestComponent extend Object
{
var $my_model; // can be either User, or Person
function test()
{
$myModelTemp = $this->my_model;
$model = $myModelTemp != 'User' ? $myModelTemp.'->User' : 'User';
$this->$model->find('all');
}
}
As you can see above in my function test() what I'm trying to do is call the correct model based on the value of my_model. So based on the condition, my query will be either:
$this->Person->User->find('all');
Or
$this->User->find('all');
When I do it like I did above, I get an error saying Fatal error: Call to a member function find() on a non-object. In order words, that error means Person->User is not an object (so, it is considered as a string).
What you're saying could be true, however, it can refer to any part of the call.
So either Person or User could be invalid, or together they causes the error. Hard to say.
Try dumping the individual objects using var_dump();
So try:
<?php
echo "<pre>";
var_dump(is_object($this->Person));
var_dump(is_object($this->User));
echo "</pre>";
?>
to determine where you're code goes wrong.
To be clear, that return value needs to be true for it to be an object.
The one that returns false is the likely culprit.
Should your question refer to the correct way to reference an object, an object is basically an array. For example:
<?php
$obj = (object) array("this", "my_function");
?>
The above example casts the array as an object. However, using multiple layers might prove to be more difficult than you'd expect.
Generally, it looks like you might be going about this all wrong. Obviously you want the models to be dynamic, but then you're hard-coding things which defeats the whole point of it being dynamic in the first place.
It also seems like you might be violating the principals of CakePHP and MVC by doing all this in a component. I'm not sure this component should really be manipulating models or assuming which models are currently in use.
However, if you want to evaluate a string as an actual object, you can wrap it in { ... } (this is valid standard PHP syntax, not Cake-specific code).
Try this:
$modelName = $this->my_model;
$model = ($modelName != 'User') ? $this->{$modelName}->User : $this->User;
$model->find('all');
Now, if this doesn't work or you get an error saying it can't find the model(s) you need to ensure the models are actually loaded and initialised in the current scope.
In Yii, the following doesn't work (the relation array remains empty) and doesn't return an error:
foreach ($data as $k => $relatedModelData){
//construct the related model from the data passed in
...
$model->arrayOfRelatedModels[] = $relatedModel;
}
Instead, I have to do this:
foreach ($data as $k => $relatedModelData){
//construct the related model from the data passed in
...
$tempArray[] = $relatedModel;
}
$model->arrayOfRelatedModels = $tempArray;
I am wondering why this is the case, or whether I have got something slightly wrong in the first example?
#o_nix is right, you should be getting the:
Indirect modification of overloaded property error. It's something i've come across a lot recently.
It means that Yii is returning you a magic attribute via the __get function, the object doesn't really exist on the class, and when you set this object it goes through the magic __set function. This means if you try and change something inside the object itself (inner array values for example) it has no idea what to do with them and so it throws up that notice and leaves it alone.
To get round this you did the right thing, modify a new local variable and set the whole object to this once you're done.
P.S
You might have your PHP configuration set to hide notices, which is why it's silent.
Hope that clears it up
I have a members.php file that shows my websites members. I echo members name by using foreach method. A method of Members class returns an array, then I use foreach loop in the members.php file to echo the members. I am trying to aovid writing as less php code as possible in my members.php file where my html files are located. Is there a way to avoid using foreach inside members.php file?
For example, is it possible to return value from a method couple of times? (by only calling the object once). Just like how we normally call the functions? This question doesn't make sense, but I am just trying to see if there is a away around this issue?
You could write an intermediate function that caches whatever the Members-method returns and return just one index from the cache, specified by a parameter. But then you are back to using a some kind of loop.
There's nothing wrong with a loop in your view. After all, PHP is a templating language.
However, you could write an object method to return/print a formatted members list.