I want this
$this->$model_name->findByProgram_id($id)
to be executed something like this
$this->$model_name->findBy.$field_id($id)
where $field_id = 'program_id
and $id
is the actual field value. This is required for dynamically calling function. Will it be possible or i should process with hard-coded field name.
Hope this will make sense!!! thanks inn advance
You can do it by using the inflector class in Cakephp, this is a concept so may need fleshing out but...
$methodName = 'findBy' . Inflector:camelize($field_id);
$this->$model_name->$methodName($id);
Although the findByXXX magic methods can be convenient at times, they are not always the most efficient way to retrieve your data.
By no means I will tell you to completely avoid using them, but there are a few things to consider when using them;
Magic methods rely on a magic __call()
method, which (if exists) is called by PHP. I'm not going to start another debate here, as several already exist. Magic methods does serve a purpose and can be used in many situations.
Just be aware that;
findById()
does not exist in your source code)find(xxx)
offersCakePHP models may have a lot of 'relations' defined. Although simply calling Model->find('all')
will give you all the data you need, in most cases it will give you more than you need. Model->find('all')
in CakePHP is the equivalent of this query in SQL;
SELECT * FROM tableA JOIN tableB JOIN tableC.....
In other words; it will fetch all related fields and records of tableA, tableB and tableC.
In most cases you don't need all that data, and queries like this are inefficient, use a lot of memory, and cause your website to perform poorly.
CakePHP has a recursive
option, that allows you to specify how deep to retrieve your data, e.g. By setting recursive = -1
, CakePHP will only retrieve data from the 'main' table, and not related tables;
SELECT * FROM tableA;
However, if you want to retrieve data from tableA and tableC but not from tableB, you're out of luck when using recursive
If you want to have finer control, use the Containable behavior
. This behavior allows you to specify exactly which relations should be included in your results, for example;
$this->ModelA->find('all', array(
'fields' => array(
'ModelA.id',
'ModelA.name',
'ModelC.name',
),
'contain' => array(
'ModelC',
)
));
As long as you're not specifying a contain
key in your find
options, the ContainableBehavior will not do anything, so it's save to add this behavior by default by adding it to the $actsAs
array of your AppModel
Whether you're using the ContainableBehavior or not, being specific is always good practice. Always check the SQL queries that are executed by CakePHP to check if they make sense. Always check the data that is returned by those queries; check if they don't contain data that you won't be using.
-1
by default in your AppModel (public $recursive = -1;
). Only set recursive to 1 or 2 if you actually need it. If so, do this on a per query basis.'ModelA.name'
instead of just 'name'
)Try to move all data-related logic/code out of your controller and move it to your Models.
To get back to your original question; create your own 'convenience' method that allows you to search your model by any field, for example; to enable searching your User Model and retrieve only the id, name and department-name
User extends AppModel
{
public $actsAs = array('Containable');
public function searchByField($field, $value)
{
return $this->find('all',
array(
'fields' => array(
'User.id',
'User.name',
'Department.name',
),
'conditions' => array(
// this will dynamically search by $field
$field => $value,
),
'contain' => array(
'Department',
)
)
);
}
}
This may seem like a lot of code, however, if you become more experienced with CakePHP, methods like this are written in less than 5 minutes. On the plus side; they will give you full control over what will be retrieved and can easily be modified to fit your needs.
In your controller, the amount of code is just one line; use it like this;
// Search by email
$data = $this->User->searchByField('User.email', 'foo@example.com');
// Search by name
$data = $this->User->searchByField('User.name', 'admin');