For anybody who has seen / used Magento, can you please tell me where can I find the following 3 function's definitions of the Catalog Product's save action's Event Observer class:-
setBundleOptionsData()
setBundleSelectionsData()
setCanSaveBundleSelections()
Please pardon me, for asking such a silly question, but I am really helpless.
Any help is greatly appreciated.
The worst part is that these above 3 methods are being used for the product object in a nice way, & they are working too. But where are their definitions?
EDIT:-
Okay, I can understand that these are used by the "Varien_Object", and these are simple setter functions using the concept of Magic Methods. But can somebody please tell what is the coding flow, when the program counter arrives at such a function, in this case in the Event Observer class?
If you have run a search on all the files and can't find the definition then these are most likely using PHP's magic methods. Is this class inheriting (directly or indirectly) from Varien_Object? If so, then these are simple setter functions storing data in an array within the object.
To get these values back all you need to do is change the 'set' to 'get':
$this->setBundleOptionsData('whatever');
echo $this->getBundleOptionsData(); //Returns 'whatever'
If you're interested in how this works, look inside class Varien_Object. I've also described the mechanism here.
Related
I have a namespace-based code, with a "Model" folder. I call my models statically everywhere in my code:
\Myapp\Model\PersonModel::doSomething()
Now, I would like to distribute my application in several countries, and be able to override some features of PersonModel for some countries (and add models for some countries, and so on).
I will have:
\MyApp\Model\France\PersonModel::doSomething()
I would like to be able to use the specialized version, with that in mind:
Not modifying too much code
Keep my IDE code completion
One solution would be to specialize every controller for every country, and use fully qualified names everywhere, but I'm not sure it is realistic (time consuming and maybe even not functional).
Another solution would be to override every model, and add a function somewhere that would give me the name of the fully qualified class (for the current country), but the code would become ugly, and I would lose code completion.
A third solution would be to have a repository for every country, and try to modify everything so that the core code is in a Git submodule and everything else is specialized classes... It seems to be the best solution to me but it seems like a Titan work, and I would prefer to have all countries inside the same repository to keep things under control.
I have really no other idea. I'm sure I'm not the only one with that problem, but I searched and found nothing. Please, tell me there is a magic feature for namespaces that I wasn't aware about, or something? :)
Edit: this is partially solved
I am now using a custom autoloader, which will load the proper country-specific class. But all country-specific classes will share the same namespace (which will work because we are using only 1 country at a given time). However, I lose code completion, but it's a tradeoff I'm ok with. If someone has a solution that would also allow to keep code completion, please feel free to answer!
Ok I found a globally satisfying solution:
All country-specific classes will share the same namespace (for example "Myapp\Model\Custom*"), which will not cause conflicts because there is only 1 country at a time.
A custom autoloader will load the proper class/file based on the current country.
Inconvenients of this solution are:
Not possible to "use" multiple countries at the same time (which is not the goal, so it's ok)
Losing code completion :(
Advantages are:
Much less time consuming and hair-pulling than creating a repo for each country
Globally clean code and code structure
Please feel free to post a more elegant solution, I will be glad to read it (and accept it)!
Another idea, following on from my thoughts in the comments. Move this:
\Myapp\Model\PersonModel
to here (random location, as I don't know your default territory):
\Myapp\Model\Germany\PersonModel
You'll now have two classes with a country in the namespace, and of course you can add more. You can now add a new generalised class, thus:
namespace \Myapp\Model;
/*
* Document your methods here using #method, so you get autocompletion
*/
class PersonModel
{
public function __callStatic($name, $args)
{
// Convert the call to an appropriate static call on the correct class.
// The first parameter is always the country name, which you can examine
// and then remove from the list. Throw an exception if $args[0] is
// empty.
}
}
You can then do this:
\MyApp\Model\PersonModel::doSomething('France', $args);
The use of #method (see here) will ensure you retain auto-completion, and you can learn more about the call magic methods here.
Of course, make sure your language-specific classes refer to a parent class, so you are not duplicating large blobs of code. Some methods may also not care about language, in which case they can go in \Myapp\Model\PersonModel, with the benefit that they do not need manual phpdoc entries.
This is my current system for a framework that I'm making:
I create an object upon a request to access a non-existing property, that has the name of an existing class through the __get function defined in the Core class. The Core class extends every class.
So it works like this:
class Someclass extends Core
{
public function classmethod()
{
$this->otherclass->method();
}
}
This works exactly how I want it to work. However, I have no idea (after a lot of frustration) how to edit/create properties of the object, using this system.
So something like this would't work.
$this->view->somevar = "newvalue"; // this doesn't work.
I guess it has to do something with the __set function, but I failed to find out.
I received the following suggestions how to tackle this problem:
Dependency injection, Namespaces, Singleton pattern.
I would love to see how to implement what I'm trying to do using one of these patterns.
I have no idea which to choose in order to achieve my simple problem: Use objects in other classes, so i don't need to put anything into __construct's parameters or using global variables.
I am using __autoload.
I hope i can tackle this problem with your help.
First of all, the architecture you're attempting is extremly bad. Aparently you are using "magic" to create objects attached as properties to other objects. Which is bad, because if you use _get/_set, you will end up in problems sooner rather than later. Also extending from a common parent is a bad thing because it generates huge inheritance trees, and it allows most of the objects to have more than one responsability.
Before starting a framework, you might want to look over: SOLID
Now coming back to your question, if you use __get for getting a value, you can as well use __set for setting a value.
__construct method is there in order to allow you to initialize the object with all the data it needs in order to fulfill his sole purpose. Avoiding the __construct is kinda stupid, and defeats the purpose. You might want to pay attention to the D in SOLID in order to see what Dependency Inversion really is and to understand it.
Using __set loses completely the ability to typehint interfaces and so on. Therefore the code can become really buggy and ijcredibly hard to follow, since the flow is not so well defined, and the allocation is done in the back via magic. Also i can come up with 1 million other reason for which the architecture you are trying to use is wrong, but i will leave that for another time.
I'm a big enthusiast about new Zend Framework. I had done one project in the previous version so far and I decided to learn new one which contains a really hard parts to understand for me.
I've watched webinars and youtube videos, also I read the documentation and I'm trying to understand this framework simply by read the code but there are few things I just can't figure out.
There is a lot information about EventManager in webinars but since I'm lack at English I'm just not able to understand 100% of the speech.
I know that event manager manage events which is quite obvious but I don't really know how to use it: in one of the webinars they provide some simple examples but they don't explain where to put this code, is it module.php file? Or some other place if you can show me some practical example with explanation so i can see whats the point.
Next thing is that mysterious $e passed as an argument to most of the functions in Module.php which after is used like this: $e->getApplication or something I just wonder what this $e stands for? It is instance of what? And next thing is how it is passed "automatically" to these functions?
Another problem: in configuration files which are specified for each module called module.config.php there is a lot of things. I got the point of routes I've understood them but I can't figure out what are the invokables and factories. It is also explained in one of the webinars as follow: invokables are paths to classes, factories are callable functions or classes (cant remember). The point is OK, that make sense in some theoretical talk but please provide me some examples with in depth explanation, where those factories and invokables come from and other stuff that I need to know.
The other thing is that there is a lot of configuration possibilities in those configuration files. Where can I find some informations about what "keys"=>"values" are possible in those files?
That's all for now but there are still unanswered questions i would like to ask. If someone is able to help me, I would really appreciate to correspond via mail with this person.
Ok one problem is solved. The one about mysterious &e so if somene is intersted in here is a solution:
This $e variable instance depends on what function we use in module.php file:
case 1: init() -> &e is an instance of module manager
case 2: onBootstrap() -> &e is an instance of MvcEvent
(if there are other cases i havent found please let us know)
The thing is that those methods are called when event has been triggered so mysterious &e is passed to those functions by listenerers which are listening if these functions appears in our code (this is my simple logic of that so please dont hate me)
There are still other questions to answer.. as soon as ill figure out some senseful answer i will let you know
Within stock ZF2 code, $e is always an instance of Zend\EventManager\EventManagerInterface. Usually it is either an Zend\EventManager\Event or an Zend\Mvc\MvcEvent.
A class' EventManager triggers an event which results in listener callbacks being called. Each listener callback is passed an instance of an Event which then has some useful methods, notably getTarget() and getParams(). Other instances of EventManagerInterface usually have more specialised methods. MvcEvent in particular has methods related to the Mvc component, such as getApplication(), getRouter(), getRequest() and getResponse().
You can find more information about tghe EventManager, application configuration and MvcEvent in the "Using Zend Framework 2" book: http://leanpub.com/using-zend-framework-2
I'm testing out somethings of Code Igniter and I noticed that code igniter doesn't provide a way to let the user set parameters in the constructor of a model.
Then I searched around a bit and I found out that someone actually find it useless to have constructor in models. Why is that?
I'd love to do things like:
$user = new User(123); // 123 = id
$user->getName();
or something like that with models. But now it turns out that we shouldn't use constructors for them.
Why should we or shouldn't we use parameters for model classes?
I'm throwing that off my hat cause i don't know anything about Code Ignitor but i know why most models usually feature a constructor less pattern.
The reason is for serialization et deserialization. Many languages (Vb.net and C# for instance) don't allow serialization based on a constructor enabled class. Because, when deserializing a class that was serialized, it would have to go through the constructor which is impossible in deserialization process because it's not part of the usual code path.
My guess is that the same thing occurs with Code Ignitor, they decided to remove the constructor for similar purposes even though there is the magic wakeup in PHP.
I think it makes sense, do you?
I've caused a circular loop between a class and it's parent class.
The only way I can think of to fix the problem is to test if there are instances of the child class in use. Is there anyway to test for that?
So I took a break and came back the issue. The loop was caused by the __construct method in a class that deals with routing input to the appropriate logic. This class is then inherited by other classes so that if I need to do something automatically that would normally be done by the user I can implement it easily.
What I didn't see happening was that each time a child class was called, this constructor was activated to reroute the user to the right code. Since the input was identical, it was sent back to child class, setting up the loop. I have solved the issue by taking out the constructor and calling the methods needed in the site index instead, so that child classes, no longer attempt to call themselves.
Well, you should adjust your code to avoid the loop. It sounds like a bad thing what you did and it's likely to cause troubles in the future. So my suggestion is to redesign your code so you avoid the loop instead of fixing it.
You could use instanceof to check if it's an instance of a class. Or is_subclass_of to check if it extends a class.
If you post your code maybe someone can suggest a better design, the loop can probably be avoided.