Is there any method in Kohana 3.2 ORM for cascade delete.I am a beginner in kohana so any one can help me in this matter?
I'm afraid there isn't in Kohana. If you really need one, you should apply it on the database level (ON DELETE CASCADE)
To cascade deletes, override the delete() method in your model:
class Model_Alpha extends ORM
{
protected $_has_many = array(
'beta' => array(
'model' => 'beta',
'foreign_key' => 'alpha_id',
),
'gamma' => array(
'model' => 'gamma',
'foreign_key' => 'alpha_id',
),
);
function delete()
{
foreach($this->beta->find_all() as $entry)
$entry->delete();
foreach($this->gamma->find_all() as $entry)
$entry->delete();
parent::delete();
}
}
You can then cascade further by overriding the delete() method on the models you're deleting.
Related
There is a serch form on the mainpage of a realestate agency. The data about objects is stored in the table "realty" that uses relations. For example, there are related tables category (residential, commercial, land plots), deal (buy, sell, rent), object_type (apartment, house, office).
Then different categories have different properties and and there are three bootstrap tabs in the search form: residential, commercial, land plots. Under each tab there are selects and input fields that are specific for the choosen tab.
In the most cases, the examples of using Search model are given within a gridview.
Is it possible to adapt Search model logic so that it could return the array of results from the table 'realty' based on the values indicated in the search form on the mainpage ?
Yes, of course you can. you have several options:
Solution 1 - worst solution but the answer to your question
modify the search function of the model (or create a new function). The search functions usually looks like this
public function search($params)
{
$query = Bookmark::find()->where('status <> "deleted"');
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => [
'pageSize' => Yii::$app->session->get(get_parent_class($this) . 'Pagination'),
],
]);
if (!($this->load($params) && $this->validate())) {
return $dataProvider;
}
$query->andFilterWhere([
'status' => $this->status,
'id' => $this->id,
'reminder' => $this->reminder,
'order' => $this->order,
'update_time' => $this->update_time,
'update_by' => $this->update_by,
'create_time' => $this->create_time,
'create_by' => Yii::$app->user->id,
]);
$query->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'url', $this->url]);
return $dataProvider;
}
You can change it to something like
public function search($params)
{
$query = Bookmark::find()->where('status <> "deleted"');
if (!($this->load($params) && $this->validate())) {
THROW AN ERROR SOMEHOW HERE
}
$query->andFilterWhere([
'status' => $this->status,
'id' => $this->id,
'reminder' => $this->reminder,
'order' => $this->order,
'update_time' => $this->update_time,
'update_by' => $this->update_by,
'create_time' => $this->create_time,
'create_by' => Yii::$app->user->id,
]);
$query->andFilterWhere(['like', 'name', $this->name])
->andFilterWhere(['like', 'url', $this->url]);
return $query->all();
}
however this will return to you all the records because ActiveDataProvider takes care of the pagination based on the query given.
Solution 2, a better solution
read the first example here http://www.yiiframework.com/doc-2.0/yii-data-activedataprovider.html . You can call ->getModels() on an ActiveDataProvider to get the actual records. No changes needed to the search function. Do whatever you want with the array.
Solution 3 and what I use all the time
Use ActiveDataProvider with a ListView. The list view allows you to create the list of records however you want, it does not have to be a table. I personally do this in many places and it works quite well. I sometimes transform arrays to an ArrayDataProvider just to use it. More about data providers here: http://www.yiiframework.com/doc-2.0/guide-output-data-providers.html
I just want the standard Excerpt box - not a metabox of my own creation, added to a Custom Post. The box shows up in Posts but not in Custom Posts. I've tried both of these older solutions but neither of them worked (maybe it's a WP 3.9 problem):
The custom post type name is "Scoop"
I added this to the register_post_type_scoop() $labels = array
'supports' => array('title','thumbnail','excerpt')
but it didn't work - neither did this:
add_post_type_support('Scoop', 'title');
add_post_type_support('Scoop', array('title', 'thumbnail', 'excerpt') );
Add a index value excerpt to the supports object. Below the example is:
add_action( 'init', 'create_testimonial_posttype' );
function create_testimonial_posttype(){
register_post_type( 'testimonials',
array(
'labels' => array(
'name' => __( 'Testimonials' ),
'singular_name' => __( 'Testimonial' )
),
'public' => true,
'has_archive' => true,
'rewrite' => array('slug' => 'clients'),
'supports' => array('title','thumbnail','editor','page-attributes','excerpt'),
)
);
}
I have a Custom Post Type using the Custom Post Type UI plugin called Case Studies. I'm also using the Custom Fields to add a capability field to the Case Studies.
How can I query Case Studies where the capability is equal to some ID?
$query = array('post_type' => 'case-studies','posts_per_page' => 3);
is my query so far
It could be
$query = array(
'post_type' => 'case-studies',
'meta_key' => 'capability',
'meta_value' => 10, // some ID
'posts_per_page' => 3
);
$the_query = new WP_Query( $query );
while ( $the_query->have_posts() ) : $the_query->the_post();
// echo here
endwhile;
wp_reset_postdata();
You need to set your key to capability, and then query value by your post ID.
'meta_query' => array(
array(
'key' => 'capability',
'value' => $post->ID,
'compare' => 'example'
)
)
I'm using the CakePHP Search Plugin, and there's something I can't get to work. I would like to have a search field (let's call it age) where a user can input a value (like 24, for example) and get as a result all the elements with a value in the age field of the table who have age 24 or higher. How can I do that?
So far I can perform normal searches, like by name or by an exact value (if you want age 24 exactly then it works fine).
Here's the code related with the Search Plugin that I have so far:
- model:
class Person extends AppModel{
var $name = 'Person';
public $actsAs = array('Searchable');
public $filterArgs = array(
array('name' => 'name', 'type' => 'like'),
array('name' => 'age', 'type' => 'value'),
);
}
- controller:
class PersonsController extends AppController {
var $name = 'Persons';
var $components = array('Search.Prg');
public $presetVars = array(
array('field' => 'name', 'type' => 'value'),
array('field' => 'age', 'type' => 'value'),
);
function index() {
$this->set('persons', $this->Person->find('all'));
}
/* ---------------- SEARCH PLUGIN --------------*/
public function find() {
$this->Prg->commonProcess();
$this->paginate['conditions'] = this->Game->parseCriteria($this->passedArgs);
$this->set('persons', $this->paginate());
}
}
- find.ctp:
//apart from the code below, I have all the code to show the results
echo $form->create('Game', array(
'url' => array_merge(array('action' => 'find'), $this->params['pass'])
));
echo $form->input('name', array('div' => false));
echo $form->input('age', array('div' => false));
echo $form->submit(__('Search', true), array('div' => false));
echo $form->end();
To sum up: with the code above, I can perfomr a search of an exact value for the age field. How do I change that to perform a search of 'age >= value entered'?
THank you so much in advance!
So this is how I solved it (or at least it seems to work with all the test I've done so far):
Changed the 'age' line by the following line in the filterArgs array in the model:
array('name' => 'age', 'type' => 'query', 'method' => 'findByAge', 'field' => 'Person.age'),
Added the following method in the same model:
public function findByAge($data = array()) {
$query = array(
'Person.age >=' => $data['age'],
);
return $query;
}
That's it! With the 'query' type, any complex query can be added to the main query using a method. Thanks to satyrwilder for pointing in the right direction!
From your presetVars -
array('field' => 'age', 'type' => 'value'),
-- filters down to your find() method from your commonProcess() method, which I presume constructs a generalized find like conditions=>array($key=>$val)?
Cake sees array key=>val pair assignments as an indication to generate a "WHERE $key=$val" condition.
To do a fuzzier pull, wherever you construct that generic find() - add a method or something just to roll those two into
'conditions'=>array("name LIKE '%{$name}%'", "{$age}>={$val}")
or whatever you've got going on. String the arguments together for the desired effect on your query and I'm sure you can extrapolate further ways to abstract that query, if needed.
If you need a more complex solution, Cake provides elegant built-in, extremely powerful subquery generation. It seems like you're working awfully hard to achieve a lot of built-in functionality, but then again I don't know how complicated your situation is.
http://book.cakephp.org/view/1030/Complex-Find-Conditions
HTH
I know this has been answered but there is another method that may be more suitable to this situation.
From the documentation
'expression' type: useful if you want to add condition that will generate by some method, and condition field contain several parameter like in previos sample used for 'range'. Field here contains 'Article.views BETWEEN ? AND ?' and Article::makeRangeCondition returns array of two values.
Full Article Here
I had to accomplish the same thing you did but with 5 different fields. I did not want to have to write a query for each one. Here is how I accomplished the same thing with the expression type. This is in the filterArgs array.
array(
'name'=>'bathrooms',
'type'=>'expression',
'method'=>'returnNumber',
'field'=>'House.bathrooms >= ?'
)
Then I created this function in the model that simply returns the number the user submitted. When called, returnNumber will be passed two arrays.
Looks something like this.
Array
(
[0] => Array
(
[bathrooms] => 6
[bedrooms] => 5
[acres] => 12
[city] => Greenville
[year] => 2009
)
[1] => Array
(
[name] => bathrooms
[type] => expression
[method] => returnNumber
[field] => House.bathrooms >= ?
)
)
Now for the actual function. You can use the debug statement to see what you are actually passing the function.
function returnNumber($arg, $name){
// debug(func_get_args());
// exit;
return $arg[$name['name']];
}
I have a CGridView widget for Lesson model
$this->widget('zii.widgets.grid.CGridView', array(
'id'=>'lesson-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
... and Lesson has relation to the User model:
'user' => array(self::BELONGS_TO, 'User', 'user_id'),
... and the CGridView has a column with user's lastname from the BELONGS_TO model described above
'columns'=>array(
...
array(
'name' => 'user',
'header'=>'Teacher',
'value' => '$data->user->lastname',
),
So, I can't symply search with CGridView in this column, but I need it.
How to search in '$data->user->secondname' with CGridView?
I think that I should extend search method in Lesson model, but how?
Now it looks like this:
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->compare('student',$this->student,true);
$criteria->compare('comment',$this->comment,true);
return new CActiveDataProvider(get_class($this), array(
'criteria'=>$criteria,
));
}
This should work, add it to your search criteria in the search() method:
$criteria->with[]='user';
$criteria->addSearchCondition("user.secondname",$this->user_id);
This is what I do though:
if(!intval($this->user_id) && is_string($this->user_id) && strlen($this->user_id) > 0) {
$criteria->with[]='user';
$criteria->addSearchCondition("user.secondname",$this->user_id);
} else
$criteria->compare('t.user_id',$this->user_id);
And here is the CGridView definition:
'columns'=>array(
...
array(
'name' => 'user_id',
'header'=>'User',
'sortable'=>false, // since it would still be sorting based on ID
// 'value' => '$data->user->lastname', // basic version
'value'=>'CHtml::link((isset($data->user))?$data->user->username:$data->user_id,array("user/view","id"=>$data->user_id))', // link version
),
It's a fun little trick: if the search term is a string and NOT an intval(), it searches for the user by their secondname, via the "user" relation. But if you enter a user_id, it will find the user by their user_id - the default search() functionality.
NOTE: This will enable filtering, but it will still sort based on ID. You will need to implement something additional to get the sorting to work.
There are surely other ways to do this, but this is how I do it. I suspect there is a "right" to do this using the relation, but my technique works solid.