This is a general question about CakePHP 3, I have a substantial OOP background, but I'm new to PHP and am stuck using Cake for a project. I guess this revolves around conventions.
So say I have some model entity, Apple, with a matching ApplesTable class. In the ApplesTable class, I've implemented a method to find something from the database. If I was in the ApplesController, my understanding is that I could write: $this->Apples->method() and it would be fine.
However, if I want to access that method in say, the OrangesController, just typing the same thing gives me a fatal error saying "Call to a member function method() on boolean." From what I found researching, it could be something with it not being able to load the model element so the method call written above would just be producing false, creating the error.
Again, I'm newer to PHP and totally new to Cake, so some of the conventions with the framework are still a little hazy. Hopefully someone can help clear this up -- thanks!
Try loadModel(), when you need to use a model table/collection that is not the controller’s default one.
// ApplesController
loadModel("Oranges");
$this->Oranges->makeJuice();
$orange_sugar = $this->Oranges->sugar;
or if your models are associated,
// ApplesController
$this->Apples->Oranges->makeJuice();
$orange_sugar = $this->Apples->Oranges->sugar;
Related
I have mock a https://github.com/elastic/elasticsearch/blob/master/core/src/main/java/org/elasticsearch/client/transport/TransportClient.java with Powermockito, before it works, but since the code chanage and add below code:
NetworkModule networkModule = new NetworkModule(settings, true, pluginsService.filterPlugins(NetworkPlugin.class), threadPool,
bigArrays, circuitBreakerService, namedWriteableRegistry, xContentRegistry, networkService);
final Transport transport = networkModule.getTransportSupplier().get();
the code alway fail at getTransportSupplier().get(), the throws exception:
Caused by: org.powermock.reflect.exceptions.MethodNotFoundException: No methods matching the name(s) get were found in the class hierarchy of class java.lang.Object.
at org.powermock.reflect.internal.WhiteboxImpl.getMethods(WhiteboxImpl.java:1720)
at org.powermock.reflect.internal.WhiteboxImpl.getMethods(WhiteboxImpl.java:1745)
at org.powermock.reflect.internal.WhiteboxImpl.getBestMethodCandidate(WhiteboxImpl.java:983)
at org.powermock.core.MockGateway$MockInvocation.findMethodToInvoke(MockGateway.java:317)
at org.powermock.core.MockGateway$MockInvocation.init(MockGateway.java:356)
at org.powermock.core.MockGateway$MockInvocation.<init>(MockGateway.java:307)
at org.powermock.core.MockGateway.doMethodCall(MockGateway.java:142)
at org.powermock.core.MockGateway.methodCall(MockGateway.java:125)
at org.elasticsearch.client.transport.TransportClient.buildTemplate(TransportClient.java:162)
networkModule.getTransportSupplier() returns Supplier.
here is code from networkModule: https://github.com/elastic/elasticsearch/blob/master/core/src/main/java/org/elasticsearch/common/network/NetworkModule.java
any idea why?
I think this is a bug with Powermock.
See that entry in their issues database; which shows the same stack trace (although for some different target). But close enough.
So, chances are, this will be fixed at some point. Or not.
Long story, short rant: I have seen too many such problems with PowerMock; thus I decided at some point that I rather fix my broken designs; instead of using the PowerMock hammer. In my experience, when we talk about "our own code"; then we simply create easy-to-test code; and then we do not need PowerMock any more. Seriously, that works. When you create your own classes, and you need PowerMock to test that; then you did something wrong! And as soon as you stop using PowerMock; you stop spending time on problems that have nothing to do with your product.
Anyway, your option space is:
Subscribe to that defect; and try to get some attention to it; the more people go there and give "me too", the more likely something will happen.
Look into your design and have a closer look why you need PowerMock(ito). And then decide if you would benefit from eliminating this requirement by changing your production code.
I have a situation where I need to perform dependent asynchronous operations. For example, check the database for data, if there is data, perform a database write (insert/update), if not continue without doing anything. I have written myself a promise based database API using promise-as3. Any database operation returns a promise that is resolved with the data of a read query, or with the Result object(s) of a write query. I do the following to nest promises and create one point of resolution or rejection for the entire 'initialize' operation.
public function initializeTable():Promise
{
var dfd:Deferred = new Deferred();
select("SELECT * FROM table").then(tableDefaults).then(resolveDeferred(dfd)).otherwise(errorHandler(dfd));
return dfd.promise;
}
public function tableDefaults(data:Array):Promise
{
if(!data || !data.length)
{
//defaultParams is an Object of table default fields/values.
return insert("table", defaultParams);
} else
{
var resolved:Deferred = new Deferred();
resolved.resolve(null);
return resolved.promise;
}
}
public function resolveDeferred(deferred:Deferred):Function
{
return function resolver(value:*=null):void
{
deferred.resolve(value);
}
}
public function rejectDeferred(deferred:Deferred):Function
{
return function rejector(reason:*=null):void
{
deferred.reject(reason);
}
}
My main questions:
Are there any performance issues that will arise from this? Memory leaks etc.? I've read that function variables perform poorly, but I don't see another way to nest operations so logically.
Would it be better to have say a global resolved instance that is created and resolved only once, but returned whenever we need an 'empty' promise?
EDIT:
I'm removing question 3 (Is there a better way to do this??), as it seems to be leading to opinions on the nature of promises in asynchronous programming. I meant better in the scope of promises, not asynchronicity in general. Assume you have to use this promise based API for the sake of the question.
I usually don't write those kind of opinion based answers, but here it's pretty important. Promises in AS3 = THE ROOTS OF ALL EVIL :) And I'll explain you why..
First, as BotMaster said - it's weakly typed. What this means is that you don't use AS3 properly. And the only reason this is possible is because of backwards compatibility. The true here is, that Adobe have spent thousands of times so that they can turn AS3 into strongly type OOP language. Don't stray away from that.
The second point is that Promises, at first place, are created so that poor developers can actually start doing some job in JavaScript. This is not a new design pattern or something. Actually, it has no real benefits if you know how to structure your code properly. The thing that Promises help the most, is avoiding the so called Wall of Hell. But there are other ways to fix this in a natural manner (the very very basic thing is not to write functions within functions, but on the same level, and simply check the passed result).
The most important here is the nature of Promises. Very few people know what they actually do behind the scenes. Because of the nature of JavaScript (and ECMA script at all), there is no real way to tell if a function completed properly or not. If you return false / null / undefined - they are all regular return values. The only way they could actually say "this operation failed" is by throwing an error. So every promisified method, can potentially throw an error. And each error must be handled, or otherwise your code can stop working properly. What this means, is that every single action inside Promise is within try-catch block! Every time you do absolutely basic stuff, you wrap it in try-catch. Even this block of yours:
else
{
var resolved:Deferred = new Deferred();
resolved.resolve(null);
return resolved.promise;
}
In a "regular" way, you would simply use else { return null }. But now, you create tons of objects, resolvers, rejectors, and finally - you try-catch this block.
I cannot stress more on this, but I think you are getting the point. Try-catch is extremely slow! I understand that this is not a big problem in such a simple case like the one I just mentioned, but imagine you are doing it more and on more heavy methods. You are just doing extremely slow operations, for what? Because you can write lame code and just enjoy it..
The last thing to say - there are plenty of ways to use asynchronous operations and make them work one after another. Just by googling as3 function queue I found a few. Not to say that the event-based system is so flexible, and there are even alternatives to it (using callbacks). You've got it all in your hands, and you turn to something that is created because lacking proper ways to do it otherwise.
So my sincere advise as a person worked with Flash for a decade, doing casino games in big teams, would be - don't ever try using promises in AS3. Good luck!
var dfd:Deferred = new Deferred();
select("SELECT * FROM table").then(tableDefaults).then(resolveDeferred(dfd)).otherwise(errorHandler(dfd));
return dfd.promise;
This is the The Forgotten Promise antipattern. It can instead be written as:
return select("SELECT * FROM table").then(tableDefaults);
This removes the need for the resolveDeferred and rejectDeferred functions.
var resolved:Deferred = new Deferred();
resolved.resolve(null);
return resolved.promise;
I would either extract this to another function, or use Promise.when(null). A global instance wouldn't work because it would mean than the result handlers from one call can be called for a different one.
I have just started a new version of my Crysis Wars Server Side Modification called InfinityX. For better management, I have put the functions inside tables as it looks neater and I can group functions together (like Core.PlayerHandle:GetIp(player)), but I have ran into a problem.
The problem is that the specified method to get the players' name, player:GetName() is being seen as an invalid method, when the method actually is completely valid.
I would like to know if using the below structure is causing a problem and if so, how to fix it. This is the first time I've used this structure for functions, but it is already proving easier than the old method I was using.
The Code:
Event =
{
PlayerConnect = function(player)
Msg.All:CenteredConsole("$4Event$8 (Connect)$9: $3"..player:GetName().." on channel "..player.actor:GetChannel());
System.LogAlways(Default.Tag.."Incoming Connect on Channel "..player.actor:GetChannel());
Event:Log("Connect", player);
end;
};
The below code works when I bypass the function and put the code directly where it's needed:
Msg.All:CenteredConsole("$4Event$8 (Connect)$9: $3"..player:GetName().." on channel "..player.actor:GetChannel());
System.LogAlways(Default.Tag.."Incoming Connect on Channel "..player.actor:GetChannel());
The Error:
[Warning] [Lua Error] infinityx/main/core.events.lua:23: attempt to call method 'GetName' (a nil value)
PlayerConnect, (infinityx/main/core.events.lua: 23)
ConnectScript, (infinityx/main/core.main.lua: 52)
OnClientEnteredGame, (scripts/gamerules/instantaction.lua: 511)
(null) (scripts/gamerules/teaminstantaction.lua: 520)
Any clarification would be appreciated.
Thanks :)
Well, as PlayerConnect is inside the table Event, and you are calling with a ":", add self as first arg in the function, like:
PlayerConnect = function(self, player)
Clearly, player in the first block of code is not the same as player in the second block of code. The problem must be that the caller of Event.PlayerConnect is not passing the same value.
To test that your Event.PlayerConnect function works, try this in the same place as your second block of code:
Event.PlayerConnect(player)
That should work as you expect.
So, the problem comes down to how Event.PlayerConnect is called without the second block of code. I'm not familiar with that game engine so I don't know how it is done. Perhaps reviewing the documentation and/or debugging that area would help. If you print(player) or call the equivalent log function in both cases, you should see they are different. If you can't run in a debugger, you can still get a stack trace with print(debug.traceback("Accessing player, who's value is: "..player)). If there is indeed some kind of table-based player object in both cases, you can try comparing their fields to see how they are different. You might need to write a simple dumping function to help with that.
Take the following code:
private var m_iQuanitity:int;
public function get quantity():int
{
return m_iQuantity;
}
That seems to make perfect sense. You can see what the quantity is from an outside class without any problems, but you can't really mess with it at all. Now take the following code:
private var m_acUsers:ArrayCollection = new ArrayCollection();
public function get users():ArrayCollection
{
return m_acUsers;
}
In that case you can't really set the variable directly, but you can still do just about everything else under the sun to it without any problems. You can call its AddItem and RemoveItemAt functions, which can do quite a bit to "set" the variable.
Does it still make sense to do this? I know you can create a duplicate ArrayCollection and just pass the duplicate back to avoid allowing it to be set, but doing stuff like that all over the place, purely for defensive programming, can waste a lot of CPU time. So I guess I'm asking if it still makes sense anyway, how so, and if I'm missing the point of using get and set completely? Thanks!
Syntactically there is nothing wrong with what you've got, but the second example does break down the concept of 'get' by making more than a read only property. If you need to adhere to a read only policy, then you've broken that since now you can manipulate the ArrayCollection.
In the end it comes down to what it is you're tying to do. Does it matter for the project that you can change the value? If you're working on a project with more than a few people, this type of coding will require you to either add a comment or have you explain what you're doing. When ever you do something outside of the norm, that can add confusion, so it's always best to simplify and stick to what is expected, avoiding having to explain something.
Also, I can think of a few ways this could cause problems - changing values outside of the function if you pass the returned property off to other classes that don't know where it came from and having internal code in the original class fail.
I am trying to do something like:
String.prototype.print=function(){trace(??????)}
I can't for the life of me figure out a way to get at the string! Yes I know there are other ways to approach this etc. but...
Not sure what the problem is, using this works fine in anonymous functions.
String.prototype.print=function():String{return "printed "+this;}
var o:Object = "foo";
trace(o.print()); // traces: printed foo
I just tricked the compiler to use an object, because "foo".print() causes
Error: Call to a possibly undefined method print through a reference with static type String.
It looks like you are mixing ActionScript 2 into your ActionScript 3 code. As kapep said, using "this" will work in your example. That is, this is perfectly valid code:
String.prototype.print=function(){trace(this)}
Of course, you are missing a semi-colon but that shouldn't matter:
String.prototype.print=function(){trace(this);} //semi-colon after 'trace(this)'
Depending on your development environment, you might be having trouble viewing trace statements, in general. In Flex Builder, for example, trace statements don't show up at all unless you are in Debug mode. Insert another call to trace to verify that you can see trace statements.
As you said, there are many other ways to approach this, such as extending the String class and adding your "Print" function. If you really can't get this to work, then trying an ActionScript 3 (i.e. Object-Oriented) approach might be your best option.