Calling $this inside Model in Phalcon - php

I need reanimate an old site, that was made by another programmer a long time ago. The site is built on Phalcon and I don't know which versions of PHP are supported.
I'm seeing many errors like:
Using $this when not in object context
It is triggered because in Models many functions calls core functions of Phalcon like $this->session->get('auth'), but it looks like a new version of PHP doesn't allow it.
How can I fix it without a total rewrite of all models?
Is there any other way to call Phalcon's $this in Model?
Or is it not possible?

If you add variable $di (factory) to your application
you need to write this :
$this->di->session->get('auth');

You are calling a static method, therefore an object has not been created and there IS NO $this.
Static methods are BAD, try and avoid! They're essentially standalone functions hiding inside a class. They're also very annoying to test.

Related

Grouping/encapsulating related functions that are across multiple php files

I'm working on an app, and part of functionality of this app is that it is extendable through addons.
The main app uses has a Render class that contains a lot of static methods that have to do with output. The actual methods interact with models/views, but the basic idea is that the Render class encapsulates methods that render something, like:
// To output "hello"
Render::sayHello();
// To output a picture of a cat wearing a hat
Render::catWithHat();
Now, from time to time addons require their own unique output functions. These output functions are very similar to the Render methods. So...
My first thought was that it would be great if I could dynamically add methods to the Render class, but after reading up about on-the-fly method creation it sounds like that's generally not considered very good practice.
So then I thought, well, I could just not encapsulate the addons' render functions at all. So that you'd just call them like:
renderMyAddonOutput();
I don't love that idea either, though.
So I guess I'm just wondering what would be considered best practice for encapsulating related functions that are declared across a variety of files.
Thoughts?
Note: if it makes any difference, I'm using Laravel for this (the very latest version).
I would consider using a Plugin pattern where an add-on registers itself into some kind of static container on init, and then you can use PHP's magic method __call() or __callStatic() to check the plugin array when a method is called that isn't found in the base class..
So if you had:
Render::pluginMethod()
then __callStatic() would check your plugin registry (which can be as simple as a static array of plugin classes or methods) and if it finds that method, it calls/returns it.

Where is the $db in CI_Model?

I come from a Java background and I am now trying to study PHP for a web project I am doing on the side written in CodeIgniter. Right now I am trying to study how to use CI's models. I am naturally very curious about reading framework code to gain a deeper understanding of how the tools I am using work.
I am really confused as to where the the "$db" in "$this->db" comes from in the Model classes that extend CI_Model come from. I checked the CI_Model class itself but it is not there.
Prior to this I have read the CI_Controller's code and somehow reckon that the although the $this->load->model(....) is not an instance variable ($this->load) with a method model(..._), somehow "it is there" because the constructor instantiates a $this->load instance variable in the constructor (the Loader class found in the core/ folder which has a model(...) function.
But for the $CI_Model I don't see the same thing. Where does the "$this->db" being referenced and when is it loaded?
I've not studied the code hard enought, but I've been using codeigniter for a while, I hope not to say something wrong, but things doesn't work as you guessed. The $db you're looking for is not in the CI_Model superclass (nor in the CI_Controller superclass), but it's a variable declared in the Loader class (system/core/loader.php).
A codeigniter application is designed to work as if it were a giant "superclass", in fact all libraries and models and so on are instantiated using $this (which usually is used in the scope of a class), so when you're loading the db library - and you can do it in your models but also in your controllers (and, if you instanciate the main $CI class in a custom library, also there) - you're in fact referring to a variable create in the loader class, precisely in line 229 (more or less) inside the database method of the CI_Loader class.
I'm not so deep in CI knowledge to give you better details, but if you take a look at the codeigniter.php and loader.php you can get enough insights to underdstand how CI internally works.
If you have other question or something's still not clear just ask ;)
$this->db might be loaded localy in the model/controller: $this->load->library('database') but most likely database library is autoloaded - check: application/config/autoload.php. For the code you should check CI_Loader class like Damien says.

Should I use App::import('Model', ...) or ClassRegistry(...)?

Because of other answers (like this), I'm just wanting to clarify what should be used in CakePHP 1.3.
Specifically, I have a situation that calls for a Model to depend on another, so from a method in that Model I'd like to load another, do some stuff with the info, etc.
The documentation for the App Class says:
In previous versions there were different functions for loading a needed class based on the type of class you wanted to load. These functions have been deprecated, all class and library loading should be done through App::import() now.
I'm assuming this covers the use of ClassRegistry, etc, but I just want to it to be clear, and certain:
Should I use App::import('Model', ...) to utilize one Model from another, or something else? If something else, what?
It appears that, even two years since 2008, the best method is to use ClassRegistry::init(), despite the cited documentation.
This is made evident in the actual API/documentation for the specific classes/methods.
App::import()
Finds classes based on $name or specific file(s) to search. Calling App::import() will not construct any classes contained in the files. It will only find and require() the file.
ClassRegistry::init()
Loads a class, registers the object in the registry and returns instance of the object.
Examples Simple Use: Get a Post model instance ClassRegistry::init('Post');
As you can see, even the API Documentation points out examples of using ClassRegistry to load models, instantiating them for you, as opposed to App::import (which does much less), and despite the changed wording in the CakePHP "Book" documentation.
If you can relate the models then the best way is to Dynamically bind the relations using
$this->bindModel("hasOne" => array("Model2")).
If you can't relate the model and you want to use the second model in just one occurrence then you can use
ClassRegistry::init('Model2')->find('allThatIWant');
if you want to use it in several occurrence then you must try
$this->model2 = & ClassRegistry::init('Model2')
$this->model2->find('allThatIWant');
As of 2.6.x of course it is ClassRegistry::init() still.
There is a major difference. App::import will just include/require it. On the other hand ClassRegistry::init() will instantiate it and fetch you a fully loaded object of the model.
So to say, for example you loaded a model in beforeFilter of your AppController. You add some custom properties to it using $this->Model->__something. Now you do call ClassRegistry::init('Model') somewhere where you do not have $controller object available, for example, in a behavior. The object returned by ClassRegistry::init('Model') will have your custom property $this->Model->__something in tact.
Btw, $controller->loadModel() seems the ideal way to load model where you have a $controller object available, for example in your components.
$this->loadModel('model name') will do unless u need it for the entire controller, Then just define the relationship in the model such as hasone, belongsto... and call $this->model->model2.

Overloading static properties with PHP

I'm trying to automate the process of accessing libraries in the framework I use (CodeIgniter) but am running in to some issues.
Codeigniter currently loads libraries like this:
$this->CI->load->library('name');
$this->CI->name->method();
Needless to say that this is a whole bunch of code for something that could be achieved with far less.
I would like to access my lib like this:
_Lib::name->method();
The _Lib class will then take care of loading the right lib (or directing the loading of that lib to the loader class in this case).
However, above code results in error "unexpected T_OBJECT_OPERATOR".
My end goal is to be able to talk to libraries and have them load on-demand with as little code as possible, and without initializing a global variable.
Any ideas? Keeping in mind that it needs to look as usable and self-explanatory as possible.
I'd like to avoid using something like _Lib('name')->method() as it's quite tedious to write that every time.
Edit:
I ended up creating a default Library which I extend my Libraries from, the default Library has properties which direct the loading of other libraries (or models, or helpers, or .. etc) to the appropreate loader, so I can do
$this->lib->name->method();
Thanks everyone for your answers
The way you've written it, _Lib::name is a class constant. Did you mean _Lib::$name->method(); ?
The "unexpected T_OBJECT_OPERATOR" error means that your call to _Lib::name did not return an object from which to chain off the method call. Technically, _Lib::name returns the value of the class constant name in _Lib. You are trying to do
class _Lib
{
const name;
}
_Lib::name->method();
but a constant cannot hold an object, so no ->.
You do not want to convert your library to static calls, because anything static couples to the global scope and is much harder to test. Just keep using what CI offers out of the box.
If you want to have one class to globally manage your other classes, consider using a Dependency Injection Container, like the one offered in Symfony Components.

Confused About Objects and Classes in CodeIgniter?

I’m fairly new to CodeIgniter and have a question. I’m a bit confused about Classes, Libraries and Objects.
Does CodeIgniter replace the normal PHP way of usings objects i.e. $var = new car(); with libraries i.e. $this->load->library('some_library'); $this->some_library->some_function(); ?
If both are valid, is there a difference? If so, what are the differences and when do I use one over the other? Which is more common/proper?
I am asking because I created a class, but I'm not certain what is the correct manner in which to instantiate it.
Thanks in advance
I am not familiar with CodeIgnitier. But familiar with other PHP frameworks. Most of frameworks use this way for performance improvements, registering things, executing certain events, and making things simpler for developer...
For example if you want to create class "car" with is somewhere in library directory you would have to include the file first before you can create object of that class (miltiple lines of code, more room for error). The framework will create the class and includes related files in 1 line of code (easier and safer).
Framework way also works as a factory. Instead of recreating an object, it will create object only once and every time you call the method again it will return the reference to existing object.
More things are happening behind the scenes when you use framework. Things are getting registered, etc...
CI doesn't replace class behavior per se, it simply adds functionality that allows access to custom libraries/models/views as singleton objects via the core object for simplicity.
Nothing is stopping you from creating (as I have in one of my projects) additional files with classes for non-singleton entities and require them in a model for further use. On hindsight, I should probably have used helpers for this.
What the loader ($this->load) class does, among other things, is it creates a single object of the specified class (model, library or view - not helpers though, see below) and attaches it as a property of the core class that is normally accessible via $this.
Helpers are a bit different. They are not attached, but instead simply 'read' into the global namespace from the point where they are loaded.
To answer your question, it would be more proper to use the loader class in instances where you don't need more than one instance of a class created. If you need 'entity' classes, your best CI-compliant bet would be to create them as helpers.
Given only this context, this looks like Inversion of Control (maybe I'm wrong, I haven't looked too closely at CodeIgniter).
You don't want to rely on the type car as in new car(). What if later you want to make $var a racecar? $var can still do the same things, but it is forced to be a car because you constructed it directly. Or what if you are testing this class, but car is some complex object which calls some external service. You want to test your logic, but don't care if the car service isn't working. So you should be able to change $var to actually load a mockcar. You can't do that if you do $var = new car().
What is Inversion of Control?

Categories