sorry for the noob question, but I don't understand why it is not returning what im expecting. Basically, it is just looking to see whether user's start and end are between the dates that exists per the id, no?
public function date_range($attribute, $params)
{
$model= Table::model();
$criteria = new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->addCondition('start_date < '.$this->start_date);
$criteria->addCondition('end_date > '.$this->end_date);
$record = $model->findAll($criteria);
if($record==true)
$this->addError('id', 'Item already exists within range.');
}
you can put the contents of this function in a better place like beforeValidate() and then return your error .
public function beforeValidate()
{
$criteria = new CDbCriteria;
$criteria->compare('id',$this->id);
$criteria->addCondition('start_date < '.$this->start_date);
$criteria->addCondition('end_date > '.$this->end_date);
$record = Table::model()->exist($criteria); // I checked for existance
if(!empty($record)) // if there are records
{
$this->addError('id', 'Item already exists within range.');
return false;
}
return parent::beforeValidate();//don't forget this line
}
Related
How do I update all rows in a table (all IDs) at once, with a database query in Laravel? My current controller code is as follows:
public function updateSchedule(Request $request, $id)
{
$timein = $request->input('timeIn');
$timeout = $request->input('timeOut');
DB::table('schedules')
->where('id', 1)
->update(['time_in' => $timein, 'time_out' => $timeout]);
}
To update the whole table (the WHOLE TABLE), you would do the following (removing the condition that you only want to update matches where id = 1):
public function updateSchedule(Request $request, $id)
{
$timein = $request->input('timeIn');
$timeout = $request->input('timeOut');
DB::table('schedules')
->update(['time_in' => $timein, 'time_out' => $timeout]);
}
If you want to see something afterwards, you either need to return that value, or a view, or a redirect to the prior page.
For example, the following (although it's not good practice to use back() as you don't know where they came from. It's better to go to a specific route / url).
public function updateSchedule(Request $request, $id)
{
$timein = $request->input('timeIn');
$timeout = $request->input('timeOut');
DB::table('schedules')
->update(['time_in' => $timein, 'time_out' => $timeout]);
return back();
}
I'm trying to learn cakephp 3 and the ORM functions, wicht is great so far. But know I'm comming to a point on wich I'm not certain how I can aproach it in the best way, so I was hoping that somebody can tell what is the best way.
I'm using the query builder to load one or more products. In the data that's loaded I have one field called price. This is the main price of the product, but there can be an optional discount for an user. I know wich user is logged in to the system so I have an variabele witch contains his discount, for example 1.20 (=20%).
After the query has been fired I could do an foreach and recalculate the price before sending is to the view, but because of the query builder function I suspect that I can do it there before I fired the query.
Below an example where an search is done on input name. The field price is now standard, but should be recalculated with the discount.This could be an foreacht example:
$price = round((($price/$User->discount)-$shipping),2);
SearchController:
public function search()
{
if ($this->request->is('post')) {
//$this->request->data);
$options = array();
$options['query'] = $this->request->data['Search']['query'];
$products = TableRegistry::get('Products');
$query = $products->find('search', $options);
$number = $query->count();
$products = $query->All();
$this->set(compact('products'));
$this->set('number_of_results',$number);
}
The ProductsTable:
public function findSearch(Query $query, array $options)
{
$query
->where([
'name LIKE' => '%'.$options['query'].'%',
"active" => 1
])
->contain(['ProductsImages'])
->select(['id','name','price','delivery_time','ProductsImages.image_url'])
;
return $query;
}
Is there an way to implement this recalculation in the query builder? I tried to find some info on the web but there isn't much information yet about the ORM options. I was thinking about maybe ->combine. Hopefully someone wants to put me in the right direction.
Thanks in forward.
Changed the controller function to:
public function search()
{
if ($this->request->is('post')) {
$options = array();
$options['query'] = $this->request->data['Search']['query'];
$discount = 2;
$products = TableRegistry::get('Products');
$query = $products
->find('search', $options);
$query->formatResults(function (\Cake\Datasource\ResultSetInterface $products) {
return $products->map(function ($row) {
$row['price'] = ($row['price'] + 10);
return $row;
});
});
$number = $query->count();
$products = $query->All();
$this->set(compact('products'));
$this->set('number_of_results',$number);
}
}
I have following tables
notice[id, type],
property[id, type],
property_value[id, notice_id, property_id, value].
Each notice has own properties specified by it's type. I need to make a filter by several properties simultaniously, and issue is how to specify which property shoud have a specified value?
class Notice extends CActiveRecord{
/** #var array property_id=>value from $_GET*/
public $searchParams= array();
public function search() {
$criteria = new CDbCriteria;
// $criteria->together = true;
$criteria->compare('t.type', $this->type);
foreach ( $searchParams as $property_id => $value) {
/// What should i write here?
/// $criteria->compare('propertyValues.id', $id);
/// $criteria->compare('propertyValues.value', $value);
}
}
}
Ps: Found this and this but i need specify params...
As i found this issue is around a classic EAV model (Entity–attribute–value). So for temporary (but no finest) solution i join value's table multiply times for every parameter:
public function search() {
foreach ($properties as $id => $value) {
$joinAlias = 'p_' . $property->id;
$join = "\nLEFT JOIN property_value as $joinAlias ON t.id= {$joinAlias}.notice_id AND {$joinAlias}.property_id='{$property_id}' ";
$criteria->compare("{$joinAlias}.value", $value);
$criteria->join .= $join;
}
}
I am working with options, to add some additional info like image. and I saved this data to my own table with option_type_id and option_id. now on frontend I would like to join my own table data to default options. so these options come with image info.
$_option->getValues()
this function returns option data, now I have to reach the implementation of this function where it generate the query so I could add join to retrieve my own data with.
I dont see a clean way to do this.
Here is a dirty way:
RewriteMage_Catalog_Model_Resource_Product_Option and add this function below.
Modify it with you join. however the join to you table would then be done for every product option. You will need to check for somekind of a flag and only add your join if this flag is set.
protected function _getLoadSelect($field, $value, $object)
{
$select = parent::_getLoadSelect($field, $value, $object);
if("do your check here"){
$select->join('your table')
}
return $select;
}
Here is what i got success from.
i overridden the resource collection of product
class MYC_COPSwatch_Model_Resource_Product_Option_Collection extends Mage_Catalog_Model_Resource_Product_Option_Collection{
public function addValuesToResult($storeId = null)
{
if ($storeId === null) {
$storeId = Mage::app()->getStore()->getId();
}
$optionIds = array();
foreach ($this as $option) {
$optionIds[] = $option->getId();
}
if (!empty($optionIds)) {
/** #var $values Mage_Catalog_Model_Option_Value_Collection */
$values = Mage::getModel('catalog/product_option_value')
->getCollection()
->addTitleToResult($storeId)
->addPriceToResult($storeId)
->addSwatchToResult($storeId) //USED Join in this function
->setOrder('sort_order', self::SORT_ORDER_ASC)
->setOrder('title', self::SORT_ORDER_ASC);
foreach ($values as $value) {
$optionId = $value->getOptionId();
if($this->getItemById($optionId)) {
$this->getItemById($optionId)->addValue($value);
$value->setOption($this->getItemById($optionId));
}
}
}
return $this;
}
might be save time for someone.
I have several models with relations and what I am trying to do is to search the fields with the aliases I provide in DetailView. It looks like this
<?php $this->widget('bootstrap.widgets.BootGridView',array(
'id'=>'operations-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'operationType.name:raw:Operation',
'creation_date:datetime',
'modification_date:datetime',
'ammount_usd:raw:Ammount',
'currency.short',
/*
'client_id',
'organization_id',
*/
array(
'class'=>'bootstrap.widgets.BootButtonColumn',
),
),
)); ?>
And what I want is to be able to search through rows using the aliases for columns like currency.short. What is a correct approach to do that? Tried to modify the search() method like this..but I think I'm missing something.
public function search()
{
// Warning: Please modify the following code to remove attributes that
// should not be searched.
$criteria=new CDbCriteria;
$criteria->compare('creation_date',$this->creation_date,true);
$criteria->compare('modification_date',$this->modification_date,true);
$criteria->compare('ammount',$this->ammount,true);
$criteria->compare('ammount_usd',$this->ammount_usd,true);
$criteria->compare('currency_id',$this->currency_id);
$criteria->compare('operation_type',operationType::model()->name);
$criteria->compare('client_id',$this->client_id);
$criteria->compare('organization_id',$this->organization_id);
$criteria->compare('comment',$this->comment);
return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
Thanks.
You have to create a virtual field for that property. For example in your main model:
private _currencyshort = null;
public function setCurrencyshort($value) {
$this->_currencyshort = $value;
}
public function getCurrencyshort() {
if ($this->_currencyshort === null && $this->currency != null)
{
$this->_currencyshort = $this->currency->short
}
return $this->_currencyshort;
}
public function search() {
$criteria=new CDbCriteria;
$criteria->with = array('currency'); // add more elements to array if you want to search by more relations
$criteria->compare('currency.short',$this->currencyshort);
// You can also add this field to your sorting criteria
// ... etc
}
Also you have to add currencyshort into your rules() method of main model to the line where it states 'on'=>'search', for example:
array('currencyshort', 'safe', 'on'=>'search'),
Then in columns instead of currency.short you can put currencyshort and it will work with filters, sorting and etc.