Something like PHP's __call() in Actionscript - php

Suppose (as an example) that I have a class which I want to log all method calls to.
In PHP this can be accomplished quickly and easily with __call(), or in Python with decorators.
What would be the easiest way to accomplish the same thing in Actionscript 3?

Extend flash.utils.Proxy and use the flash.utils.flash_proxy namespace. There's methods similar to __get, __set and methods for delete methods as well. For example, the __call method is:
override flash_proxy function callProperty(name:*, ...rest):*;
so if have a class that extends Proxy, you do:
var test:MyObject = new MyObject();
test.myMethodThatIsntDefined("param");
then callProperty will be called and name will be set to "myMethodThatIsntDefined" and "param" will be in the ...rest array.
The link to the asdoc has a simple implementation that should get you going. I typically use the Proxy class for something like an API. For example, back in the day I had a Flickr API wrapper that translated the name of the function call to an API method name in the Flickr API. Something like:
flickr.galleriesGetPhotos();
and in the callProperty I'd split on the first word to get the API name "flickr.galleries.get_photos". The names were different back then I think.

You can try using the Proxy class.
dynamic class MyProxy extends Proxy {
flash_proxy override function callProperty(name:*, ...rest):* {
try {
// custom code here
}
catch (e:Error) {
// respond to error here
}
}
Refer:http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/flash/utils/Proxy.html

Related

How can I efficiently structure this code in Laravel?

I have a class called Sharer, which accepts a Service interface in the construct method. Service can be FacebookService or TwitterService and so on. Each Service class has a post method, that posts whatever array data you pass to that method, using its own connection (either facebook, twitter in this example).
Now the Sharer class normalizes data before sending it to that service's post method. By normalizing, it checks whether the thing we are sending to that post method is just a simple array or a Model class. Model can be either Project model, or Image model, or Video model and so on.
If it is a model class, then it calls that specific model's transformer. Transformers are just helper classes, that accept the model instance and they have two methods - facebook and twitter in this case. And each method returns a formatted array, specific to the connection.
So for example, facebook method grabs the required fields (that are needed to post on facebook) from the model and sends that array back. And twitter method does the same for twitter's required fields.
Now the thing I am a bit stuck with, is calling that specific method on the transformer class. I want to do something like this:
if(we are sharing on facebook) {
then call the facebook method
}
if(we are sharing on twitter) {
then call the twitter method
}
but obviously I want to somehow make it dynamic and not have these if statements. What would be a better approach to this?
I solved it doing this:
$method = $this->resolveMethodToCall();
protected function resolveMethodToCall()
{
$reflection = new ReflectionClass($this->service); // service being either a FacebookService class or TwitterService
$shortName = $reflection->getShortName();
return strtolower(str_replace('Service', '', $shortName));
}
Probably not the best solution, but works well and after this I am checking if the resolved method actually exists on the transformer class and throw an exception if it doesn't.

What's going on with this class constructor function in the PHP MailChimp API wrapper?

I'm going to start using the MailChimp API wrapper for PHP and I've come across something I don't understand.
The code is set up with a root file called Mailchimp.php which requires other .php files with classes for specific API calls (e.g. Templates, Campaigns, Lists, etc).
The parent class is called Mailchimp. Inside this class, the sub-files are instantiated by lines such as this:
$this->campaigns = new Mailchimp_Campaigns($this);
Inside the Campaigns.php file we have the class Mailchimp_Campaigns. The constructor for this class (which does not extend the parent) is called like this:
<?php
class Mailchimp_Campaigns {
public function __construct(Mailchimp $master) {
$this->master = $master;
}
...
My question is: what's going on with the (Mailchimp $master) part? I understand that $master is really $this from the main class, but what's the Mailchimp part? Is that similar to a namespace, or is it simply to identify that it's an object of the Mailchimp class?
The Mailchimp part is the kind of object expected to be passed to the constructor.
This is called type hinting. See this link for more info:
http://php.net/manual/en/language.oop5.typehinting.php

Include PHP Scripts which run functions?

I am looking to create a plugin manager like program which starts a loop that searches for .php files in the 'plugins' folder. I need this to somehow run a function called main() in each file which will then run other functions. How could i accomplish this without the other main() functions clashing and would there be any better alternative?
If you want to use functions then you can namespace them. But for something like this id use classes. for example each plugin might have a PluginConfiguration class which could either be namespaced like PluginName\PluginConfiguration or faked like PluginName_PluginConfiguration.
Then you could jsut instatiate these classes and invoke whatever for example:
class MyCool_Plugin implements PluginInterface {
// note the interface wouldnt be absolutely necessary,
// but making an interface or abstract class for this would be a good idea
// that way you can enforce a contractual API on the configuration classes
public function __construct() {
// do whatever here
}
public function main() {
// do whatever here
}
}
UPDATE:
By the way, what would 'PluginInterface' include?
Well an interface defines all methods (functions) a class must implement. You can use it to enforce a minimum API on any class the implements that interface. From your description this would be the method main although during development you may find that you need/want to add more.
Interface PluginInterface {
public function main();
}
You can also use type hinting to enforce a specific method signature. For example lets say you always want to inject the Application instance thats loading the plugin into the plugin itself so it can register things or set up additional stuff. In that case you might do:
Interface PluginInterface {
public function main(Application $app);
}

PHP: Passing Interface as Parameter

In .NET I have done that I passed Interfaces as parameters in class methods. I want to know is it possible in PHP?
My scnerio is that I have a class dealing with mqin system functionality. Now I want to integrate Notification system with it. I want to keep notification system separate since it is not the main part of the system plus I can use it somewhere else. If I have the following structure:
Interface INotification
{
public set()
public send()
}
And then I do:
class MyClass
{
public setNotifier(INotification $notifier)
{
}
}
So Is it possible that I can access set() and send() here after implementing them in a class? I want to know how this C# Example work that they set parameters of an Interface type.
Thanks
Yes, it is possible, pretty much as you wrote. Example of such interface: http://api.nette.org/2.0/source-Http.IResponse.php.html#18 and example of such parameter: http://api.nette.org/2.0/source-Http.Context.php.html#32
Yes, you can do as you coded. You can find more information and examples on php.net.
Note that specifying the type in the method parameter (type hinting) is allowed (PHP >= 5), but not required.

Mock Objects in PHPUnit to emulate Static Method Calls?

I am trying to test a class that manages data access in the database (you know, CRUD, essentially). The DB library we're using happens to have an API wherein you first get the table object by a static call:
function getFoo($id) {
$MyTableRepresentation = DB_DataObject::factory("mytable");
$MyTableRepresentation->get($id);
... do some stuff
return $somedata
}
...you get the idea.
We're trying to test this method, but mocking the DataObject stuff so that (a) we don't need an actual db connection for the test, and (b) we don't even need to include the DB_DataObject lib for the test.
However, in PHPUnit I can't seem to get $this->getMock() to appropriately set up a static call. I have...
$DB_DataObject = $this->getMock('DB_DataObject', array('factory'));
...but the test still says unknown method "factory". I know it's creating the object, because before it said it couldn't find DB_DataObject. Now it can. But, no method?
What I really want to do is to have two mock objects, one for the table object returned as well. So, not only do I need to specify that factory is a static call, but also that it returns some specified other mock object that I've already set up.
I should mention as a caveat that I did this in SimpleTest a while ago (can't find the code) and it worked fine.
What gives?
[UPDATE]
I am starting to grasp that it has something to do with expects()
I agree with both of you that it would be better not to use a static call. However, I guess I forgot to mention that DB_DataObject is a third party library, and the static call is their best practice for their code usage, not ours. There are other ways to use their objects that involve constructing the returned object directly. It just leaves those darned include/require statements in whatever class file is using that DB_DO class. That sucks because the tests will break (or just not be isolated) if you're meanwhile trying to mock a class of the same name in your test--at least I think.
When you cannot alter the library, alter your access of it. Refactor all calls to DB_DataObject::factory() to an instance method in your code:
function getFoo($id) {
$MyTableRepresentation = $this->getTable("mytable");
$MyTableRepresentation->get($id);
... do some stuff
return $somedata
}
function getTable($table) {
return DB_DataObject::factory($table);
}
Now you can use a partial mock of the class you're testing and have getTable() return a mock table object.
function testMyTable() {
$dao = $this->getMock('MyTableDao', array('getMock'));
$table = $this->getMock('DB_DataObject', ...);
$dao->expects($this->any())
->method('getTable')
->with('mytable')
->will($this->returnValue($table));
$table->expects...
...test...
}
This is a good example of a dependency in your code - the design has made it impossible to inject in a Mock rather than the real class.
My first suggestion would be to try and refactor the code to use an instance rather than a static call.
What's missing (or not?) from your DB_DataObject class is a setter to pass a prepared db object before calling the factory method. That way you can pass a mock or a custom db object (with the same interface) should the need arise.
In your test setup:
public function setUp() {
$mockDb = new MockDb();
DB_DataObject::setAdapter($mockDb);
}
The factory() method should return the mocked DB instance. If it's not already integrated into your class, you will probably have to refactor the factory() method as well to make it work.
Are you require/including the class file for DB_DataObject in your test case? If the class doesn't exist before PHPUnit tries to mock the object you can get errors like this.
With PHPUnit MockFunction extension plus runkit you can also mock static methods. Be careful, because it's monkey patching and therefore should only be used in extreme cases. Does not substitute good programming practices.
https://github.com/tcz/phpunit-mockfunction

Categories