I have problem with phalcon framework namely with models methods...
As you know models has included methods find() and findFirst()
I have generated model with phalcon-dev tools and now I am trying to do Model::find on it but I am getting an exception but dont know why...
There is some more informations (e.g stacktrace) :
http://exception.mateuszmarzecki.pl/
You can try change methods in model file
public static function find($parameters = array())
{
return self::find($parameters);
}
Does not look like your passing it the right parms.
SELECT FROM `nacionality`
Notice that your not selecting any fields from the database, and that is why your getting the Exception.
So... after some time of debugging I've found the problem...
For the next generation... if you don't want to lose a week as I did. Just read carefully your application config.
Problems occurs because I missed table and column annotations as well.
In my application config I have something like:
$metaData->setStrategy(new \Engine\Db\Model\Annotations\Metadata());
so Phalcon was looking for annotations in my model files, more info about this you can find there:
https://forum.phalconphp.com/discussion/1933/column-types-for-model-annotations
Happy New Year
Related
I just switched an existing Model to be Versionable.
After debugging quite a lot, I now realized that there are a quite a few cases that I use $this->save() in the model quite a few times and that this finally causing duplicate entries in the Version table.
Is the only way to prevent this by removing the -save() methods out of the model (I tried it out, it works) or is there another, more simple way to prevent the internal loop during version-creation and its saving?
Since you don't specify a version of Propel, I'm assuming the stable version 1.x, though the following might well apply to 2.x, which is in alpha5 at the time of writing.
As per this documentation, you can specify when it is appropriate to save a new version of model rows using this method:
class Book extends BaseBook
{
public function isVersioningNecessary($con = null)
{
return $this->getISBN() !== null && parent::isVersioningNecessary($con);
}
}
If that method returns false, the last version is overwritten; if it is true, a new version is created.
(The docs are slightly wrong in that I assume the parent should take a $con parameter: missing there, fixed here).
I'm a little confused as to what is going on here, it looks to me like a method is calling itself? I'm trying to learn about Magento's models. I was working my way back from a helper (catalog/category) and I got to a call on this method "GetCategories". I don't know whats going on here. If anyone could shed light on this code snippet I greatly appreciate it.
getCategories ( $parent,
$recursionLevel = 0,
$sorted = false,
$asCollection = false,
$toLoad = true
){
$categories = $this->getResource()
->getCategories($parent, $recursionLevel, $sorted, $asCollection, $toLoad);
return $categories;
}
Not much to add to #hakra's answer. Just a portion of Magento-specific logic.
So to work with Magento models you should know, that Magento has 2 types of Models: normal models, and resource models (we can call assign Blocks to the models too, as a view models - but that is more connected to the V part of MVC).
The resource models were created as a DB adapters that contain only DB-related logic, and often are connected to some DB table, hence contain the logic for CRUD operations with that table. So you'll see smth like this regularly - for the simplicity someMethod is a part of normal model, but since it contains DB-related logic, all the implementation of the method was moved to the resource model, so the body of someMethod in the regular model will be something like that:
public function someMethod($args)
{
return $this->getResource()->someMethod($args);
}
It is hard to say for the code you've posted. Even both methods share the same name (getCategories) it must not mean that they are of the same class or even object.
If you want to find out you would need to compare:
var_dump($this === $this->getResource());
Apart from that, it is also common in programming recursion that a method calls itself, hence recursion. However for that chunk of code, it would run against the wall.
So technically speaking I would do the assumption that in your example this is not the exact same object method.
Please take note that this answer is independent to Magento, it's just how PHP works generally.
I am currently a beginner in CakePHP, and have played around with CakePHP 1.3, but recently CakePHP 2.0 has been released.
So far I like it but the only thing is being a pain is the fact that it doesn't return Objects, rather it just returns arrays. I mean, it hardly makes sense to have to do $post['Post']['id']. It is (in my opinion) much more practical to just do $post->id.
Now after Google I stumbled upon this link, however, this kept generating errors about indexes not being defined when using the Form class (guessing this is because it was getting the objectified version rather than the array version).
I am following the Blog tutorial (already have followed it under 1.3 but going over it again for 2.0)
So, anyone know how to achieve this without it interfering with the Form class?
Hosh
Little known fact: Cake DOES return them as objects, or well properties of an object, anyway. The arrays are the syntactical sugar:
// In your View:
debug($this->viewVars);
Shwoing $this is a View object and the viewVars property corresponds with the $this->set('key', $variable) or $this->set(compact('data', 'for', 'view')) from the controller action.
The problem with squashing them into $Post->id for the sake of keystrokes is Cake is why. Cake is designed to be a heavy lifter, so its built-in ORM is ridiculously powerful, unavoidable, and intended for addressing infinity rows of infinity associated tables - auto callbacks, automatic data passing, query generation, etc. Base depth of multidimensional arrays depends on your find method, as soon as you're working with more than one $Post with multiple associated models (for example), you've introduced arrays into the mix and there's just no avoiding that.
Different find methods return arrays of different depths. From the default generated controller code, you can see that index uses $this->set('posts', $this->paginate()); - view uses $this->set('post', $this->Post->read(null, $id)); and edit doesn't use $this->set with a Post find at all - it assigns $this->data = $this->Post->read(null, $id);.
FWIW, Set::map probably throws those undefined index errors because (guessing) you happen to be trying to map an edit action, amirite? By default, edit actions only use $this->set to set associated model finds to the View. The result of $this->read is sent to $this->data instead. That's probably why Set::map is failing. Either way, you're still going to end up aiming at $Post[0]->id or $Post->id (depending on what you find method you used), which isn't much of an improvement.
Here's some generic examples of Set::map() property depth for these actions:
// In posts/index.ctp
$Post = Set::map($posts);
debug($Post);
debug($Post[0]->id);
// In posts/edit/1
debug($this-viewVars);
debug($this->data);
// In posts/view/1
debug($this-viewVars);
$Post = Set::map($post);
debug($Post->id);
http://api13.cakephp.org/class/controller#method-Controllerset
http://api13.cakephp.org/class/model#method-Modelread
http://api13.cakephp.org/class/model#method-ModelsaveAll
HTH.
You could create additional object vars. This way you wouldn't interfere with Cake's automagic but could access data using a format like $modelNameObj->id; format.
Firstly, create an AppController.php in /app/Controller if you don't already have one. Then create a beforeRender() function. This will look for data in Cake's standard naming conventions, and from it create additional object vars.
<?php
App::uses('Controller', 'Controller');
class AppController extends Controller {
public function beforeRender() {
parent::beforeRender();
// camelcase plural of current model
$plural = lcfirst(Inflector::pluralize($this->modelClass));
// create a new object
if (!empty($this->viewVars[$plural])) {
$objects = Set::map($this->viewVars[$plural]);
$this->set($plural . 'Obj', $objects);
}
// camelcase singular of current model
$singular = lcfirst(Inflector::singularize($this->modelClass));
// create new object
if (!empty($this->viewVars[$singular])) {
$object = Set::map($this->viewVars[$singular]);
$this->set($singular . 'Obj', $object);
}
}
}
Then in your views you can access the objects like so:
index.ctp
$productsObj;
view.ctp
$productObj->id;
All we're doing is adding 'Obj' to the variable names that Cake would already provide. Some example mappings:
Products -> $productsObj
ProductType -> $productTypesObj
I know this is not perfect but it would essentially achieve what you wanted and would be available across all of your models.
While I like the idea Moz proposes there are a number of existing solutions to this problem.
The quickest one I found is https://github.com/kanshin/CakeEntity - but it looks like you might need to refactor it for 2.x - there might even already be a 2.x branch or fork but I didn't look.
I also ran this question couple of time in my head. Now a few Cake based apps later, I see the benefit to be able to branch and merge (am, in_array etc.) result sets more conveniently with arrays than using objects.
The $Post->id form would be a sweet syntactic sugar, but not a real benefit over arrays.
You could write a function that iterates over your public propertys (see ReflectionClass::getProperties) and save it in an array (and return the array).
If you have access to the class, you can implement the ArrayAccess Interface and easily access your object as an array.
P.S.: Sorry, i've never used CakePHP but i think object-to-array conversion doesn't have to be a framework specific problem
I'm creating a behavior that log to a table the sql query executed by a particular Model in a controller. Looking for a method to return me the sql query executed for a particular finder method (like $this->MyModel->find('all') ) I found on the bakery that I can use $this->MyModel->find('sql'), but doesn't work for me. Someone knows how can I achieve this?
Thanks in advance
You can put this function in your app_model.php:
function getLastQueries()
{
$dbo = $this->getDatasource();
$logs = $dbo->_queriesLog;
return $logs;
}
And call it from any model ($this->getLastQueries()) or controller ($this->Model->getLastQueries()) to get them.
$this->Model->find('sql') is not supported natively by Cake. You have to follow the rest of the instructions in the Bakery article for installing a new DBO driver, and adding support for the find('sql') method in your AppModel. Once you do this, it should be able to get you what you're looking for.
http://bakery.cakephp.org/articles/grant_cox/2008/06/23/get-the-find-query-sql-rather-than-query-result
In cake 1.2 there is a feature that allows the developer to no have to create models, but rather have cake do the detective work at run time and create the model for you. This process happens each time and is neat but in my case very hazardous. I read about this somewhere and now I'm experiencing the bad side of this.
I've created a plugin with all the files and everything appeared to be just great. That is until i tried to use some of the model's associations and functions. Then cake claims that this model i've created doesn't exist. I've narrowed it down to cake using this auto model feature instead of throwing and error! So i have no idea what's wrong!
Does anybody know how to disable this auto model feature? It's a good thought, but I can't seem to find where i've gone wrong with my plugin and an error would be very helpful!
There's always the possibility to actually create the model file and set var $useTable = false.
If this is not what you're asking for and the model and its associations actually do exist, but Cake seems to be unable to find them, you'll have to triple check the names of all models and their class names in both the actual model definition and in the association definitions.
AFAIK you can't disable the auto modelling.
Cake 1.2
It's a hack and it's ugly cus you need to edit core cake files but this is how i do it:
\cake\libs\class_registry.php : line 127ish
if (App::import($type, $plugin . $class)) {
${$class} =& new $class($options);
} elseif ($type === 'Model') {
/* Print out whatever debug info we have then exit */
pr($objects);
die("unable to find class $type, $plugin$class");
/* We don't want to base this on the app model */
${$class} =& new AppModel($options);
}
Cake 2
Costa recommends changing $strict to true in the init function on line 95 of Cake\Utility\ClassRegistry.php
See Cake Api Docs for init
ClassRegistry.php - init function
Use
var $useTable = false;
in your model definition.
Delete all cached files (all files under app/tmp, keep the folders)
In most cases where models seem to be acting in unexpected ways, often they dont include changes you've made, it is because that cake is useing an old cached version of the model.
Uh...where do we start. First, as Alexander suggested, clear your app cache.
If you still get the same behaviour, there is probably something wrong with the class and/or file names.
Remember the rules, for controller:
* classname: BlastsController
* filename: blasts_controller.php
for model:
* classname: Blast
* filename: blast.php
Don't foget to handle the irregular inflections properly.