I would like to get the var $param from file blockcart.php in the module block cart and put it in a cookie. I'm not so good in POO so can anyone tell me what is wrong with my code.
public function hookAjaxCall($params)
{
global $cookie; //mycode
if (Configuration::get('PS_CATALOG_MODE'))
return;
$this->assignContentVars($params);
$res = $this->display(__FILE__, 'blockcart-json.tpl');
$cookie->__set('test', $param); //my code
return $res;
}
The __set is a "magic method" not for use directly. Use this coding form instead:
$cookie->test = $params;
$cookie->write();
The __set() function will handle the assignment of the new member variable you have created. Likewise you can use:
global $cookie;
if (isset($cookie->test))
// Use $cookie->test in your custom code
Related
I'm initiating a CFC like this.
<cfscript>
lock scope="application" timeout="5" {
application.mycfc = new mycfc();
}
writeOutput(application.mycfc.readVars());
</cfscript>
In the CFC, I'm setting some properties.
component output="false" accessors="true" {
property name="title";
property name="foo";
this.title = "mycfc";
function init() {
this.foo = "bar";
// I can now properly read this.title, or this.foo.
return this;
}
function readVars() {
// Here, I can read this.title, from the constructor space, but I can't
// read this.foo. It's just blank (because the default value of the
// `default` attribute of `property` is "")
}
}
Because of the implementation (caching in Application), I can instead use application.mycfc.foo in readVars().
Because of this name, it's hard to Google for details. I thought it would be persistent throughout the CFC's life, but apparently it is not?
I surely could do something like
var self = application[this.title]; // or application.mycfc
Or perhaps even
this = application[this.title];
In functions where I want to get/set without typing application.mycfc each time.
Just trying to make sure I'm not doing something wrong, or reinventing the wheel.
In my real implementation, I'm pulling from rows from a database to populate a struct.
Scopes in ColdFusion components (.cfc):
this
is the public scope, read/write from anywhere
properties
is a magical scope, read/write only via accessors (a.k.a. getters/setters) from anywhere
variables
is the private scope, read/write only within your component
All of these scopes can coexist, but this.x is NOT the same field as property name="x"!
Since you are using a component with accessors="true", all your property fields can only be read via getter and written via setter. So if you want to write your title property, use setTitle("mycfc"); instead of this.title = "mycfc";. Same goes for the foo property. Use setFoo("bar"); instead of this.foo = "bar";. If you want to read the properties, use application.mycfc.getTitle() and application.mycfc.getFoo(). If you want to set properties at runtime, use application.mycfc.setTitle("something"). Note that writing to a shared scope such as application should happen in a cflock to avoid race conditions (thread-safety).
If you don't need accessors at all, you can simply use public fields instead (accessors is missing here, i.e. set to false):
component output="false" {
this.title = "mycfc";
this.foo = "";
function init() {
this.foo = "bar";
return this;
}
function readVars() {
return this;
}
}
application.mycfc = new mycfc();
writeOutput(application.mycfc.title); // mycfc
writeOutput(application.mycfc.foo); // bar
application.mycfc.title = "something";
writeOutput(application.mycfc.title); // something
writeOutput(application.mycfc.foo); // bar
Public fields are usually not recommended though as they break encapsulation.
I've got a method in UsersController
public function addMailbox($data)
{
$this->LoadModel('Mailbox');
$mailbox = $this->Mailbox->newEntity();
$mailbox->username = $data('username');
$mailbox->name = $data('name');
if ($this->Mailbox->save($mailbox)) {
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('Error'));
}
, the code works fine when pasted into the add() method, but after using
$this->addMailbox($this->request->getData());
all i get is
error: Function name must be a string
Any ideas?
You've got the wrong syntax for accessing arrays in PHP, use square brackets:
$mailbox->username = $data['username'];
$mailbox->name = $data['name'];
The way you've got it, it's trying to call a function with the variable named in $data, but $data is an array not a string (see Variable functions for more info on that).
Also you shouldn't set user input on $mailbox properties directly - this bypasses validation. Instead just stick $data in newEntity():
public function addMailbox($data)
{
$this->loadModel('Mailbox'); // This also is not required if this function is inside the MailboxController
$mailbox = $this->Mailbox->newEntity($data);
if ($this->Mailbox->save($mailbox)) {
return $this->redirect(['action' => 'index']);
}
$this->Flash->error(__('Error'));
}
Most of the answers I have seen on StackOverflow are without using the DateTime object, and are instead using the date() function. This makes them very dirty solutions (overriding date(), mocking a protected function of the subject under test, etc).
Is there a way to mock DateTime, effectively mocking the current date/time?
As an example, here is the code I'd like to test:
public function __construct(UserInterface $user, EntityManager $manager)
{
$this->user = $user;
$this->manager = $manager;
}
public function create(Tunnel $tunnel, $chain, $response)
{
$history = new CommandHistory();
$history->setTunnel($tunnel)
->setCommand($chain)
->setResponse($response)
->setUser($this->user)
;
$this->manager->persist($history);
$this->manager->flush();
}
Here is where I set the date and time in my CommandHistory class:
class CommandHistory
{
// Property definitions...
public function __construct()
{
$this->time = new \DateTime();
}
}
And here is my unit test:
public function testCreate()
{
$user = new User();
$manager = $this->mockManagerWithUser($user);
$tunnel = $this->tunnel;
$chain = 'Commands`Chain';
$response = 'This is the response!';
$creator = new CommandHistoryCreator($user, $manager);
$creator->create($tunnel, $chain, $response);
}
protected function mockManagerWithUser(UserInterface $user)
{
$manager = \Mockery::mock('Doctrine\ORM\EntityManager');
$manager->shouldReceive('persist')->once()->with(\Mockery::on(function(CommandHistory $argument) use ($user) {
return
$argument->getCommand() === 'Commands`Chain'
&& $argument->getResponse() === 'This is the response!'
&& $argument->getTunnel() === $this->tunnel
&& $argument->getUser() === $user
;
}));
$manager->shouldReceive('flush')->once()->withNoArgs();
return $manager;
}
As you can see, I've created a rather long-winded closure only to exclude the comparison of the field that contains the current time, and I feel like this is hurting the readability of my test.
Also, to preserve ease of use for people who are using this class, I don't want to have to make them pass in the current time to the create() function. I believe adding strange behavior to my classes only to make them testable means I'm doing something wrong.
So the standard approach to solving this relies on accepting that in your current implementation you have a static, implicit, undeclared dependency on an object which provides the current time (wrapped in a the new instance of the DateTime object). If you did this with your own code (rather than a class from the framework/language) you would not be able to test easily either.
The solution is to stop using the implicit undeclared dependency and declare your implicit dependency explictly. I would do this by creating a DateTimeProvider (or DateTimeFactory) interface which has a method GetCurrentDateTime. Pass this into your constructor for your CommandHistoryCreator and pass it into the CommandHistory constructor. The CommandHistory will then ask the provider to get the current date time object rather than creating a new one itself, and can carry on as it is.
This will allow you to provider a mock DateTime in your tests and check that the CommandHistory is persisted with the correct DateTime
Whenever I use a for ... in loop, the index variable of the loop always seems to be in the variables scope.
For example if I have a component with a method that uses this loop:
for(key in params){
writeOutput(key);
}
The variable 'key' will be placed in the variables scope. If I already have declared a variables.key anywhere in the component, this value gets overwritten when I use this for ... in loop. What I actually need is something like this:
for(var key in params){
writeOutput(key);
}
This however throws a parsing error.
Is there any way to put the for ... in index in a different scope then the variables scope?
The default scope inside CFCs is variables if you don't var beforehand.
You have to var the index outside the loop like so:-
var key = "";
for(key in params){
writeOutput(key);
}
An alternative approach, to avoid varring everything within your functions, is to declare your variables within a "local" structure. In CF9 a local scope is built in but for CF8 or below do something like this:-
var local = structNew();
for(local.key in params){
writeOutput(local.key);
}
This syntax will work in ColdFusion 9 and higher:
for ( var key in params ){
writeOutput( key );
}
I've got a class that's meant to validate input fields to make sure the value is always a decimal. I've tested the regex here: http://livedocs.adobe.com/flex/3/html/help.html?content=validators_7.html, and it looks like it does the right thing, but in my app, I can't seem to get it to match to a number format.
Class Definition:
public class DecimalValidator {
//------------------------------- ATTRIBUTES
public var isDecimalValidator:RegExpValidator;
//------------------------------- CONSTRUCTORS
public function DecimalValidator() {
isDecimalValidator = new RegExpValidator();
isDecimalValidator.expression = "^-?(\d+\.\d*|\.\d+)$";
isDecimalValidator.flags = "g";
isDecimalValidator.required = true;
isDecimalValidator.property = "text";
isDecimalValidator.triggerEvent = FocusEvent.FOCUS_OUT;
isDecimalValidator.noMatchError = "Float Expected";
}
}
Setting the source here:
public function registerDecimalInputValidator(inputBox:TextInput, valArr:Array):void {
// Add Validators
var dValidator:DecimalValidator = new DecimalValidator();
dValidator.isDecimalValidator.source = inputBox;
dValidator.isDecimalValidator.trigger = inputBox;
inputBox.restrict = "[0-9].\\.\\-";
inputBox.maxChars = 10;
valArr.push(dValidator.isDecimalValidator);
}
And Calling it here:
registerDecimalInputValidator(textInput, validatorArr);
Where textInput is an input box created earlier.
Clearly I'm missing something simple yet important, but I'm not entirely sure what! Any help would be much appreciated.
I don't know ActionScript, but as far as I know it's an ECMAScript language, so I expect you need to escape the backslashes if you use a string to define a regex:
isDecimalValidator.expression = "^-?(\\d+\\.\\d*|\\.\\d+)$";
This strikes me as wrong; but I can't quite put my finger on it. For your DecimalValidator instead of composing a RegExpValidator; why not extend it?
public class DecimalValidator extend RegExpValidator{
//------------------------------- CONSTRUCTORS
public function DecimalValidator() {
super()
this.expression = "^-?(\d+\.\d*|\.\d+)$";
this.flags = "g";
this.required = true;
this.property = "text";
this.triggerEvent = FocusEvent.FOCUS_OUT;
this.noMatchError = "Float Expected";
}
}
How when is the registerdecimalInputValidator called? I have a slight worry about the Validator instance is a local variable to a method instead of 'global' property to the function.
protected var dValidator:DecimalValidator = new DecimalValidator();
public function registerDecimalInputValidator(inputBox:TextInput):void {
dValidator.isDecimalValidator.source = inputBox;
dValidator.isDecimalValidator.trigger = inputBox;
}
I'm not sure why you are setting restrictions on the TextInput in the registerDecimalInputValidator method; that should be done when you create the method (in createChildren() or possibly in response to public properties changing, in commitProperties . It is also not obvious to me what the validatorArr does. If you're expecting to access values inside the validatorArrray outside of the method; it would often be a common practice to return that value from the method. Without looking it up; I'm not sure if Arrays are passed by value or reference in Flex.