in my db structure
service_request type enum('towel','tissue','napkin')
then have a model
* #property string $service_request
then in my view
<?= $form->field($model, 'service_request')->checkBoxList([ 'towel' => 'Towel', 'tissue' => 'Tissue', 'napkin' => 'Napkin']) ?>
then when i choose towel, tissue and napkin then submit the form, it's have an error said
Service Request must be String
please help me
Thank You
Like Joji Thomas said, checkBoxList prodices an array.
You need to change your database structure so that it supports 1-to-many relations (each $model can have multiple service_requests) if you want to save this. Unfortunately Yii is not very good at this sort of thing out of the box so you have to do a bunch of things yourself.
First you need to create a ServiceRequest ActiveRecord.
Then your $model needs to have a relation like:
public function getServiceRequests() {
return $this->hasMany(ServiceRequest::className(), ['model_id' => 'id'];
}
Then in your controller (model create action) you will need to do something like this:
foreach (Yii::$app->request->post('ServiceRequest',[]) as $data) {
$item = new ServiceRequest($data);
$model->link('serviceRequests', $item);
}
If you wanna update the checkboxes too then you need to do something similar in your model update action as well.
Please change checkBoxList to radioList, because when selecting multiple values service_request becomes an array. Enum type can handle only string values.
First change your filed datatype from enum to varchar. enum only takes a single string value.
Secondly you need to implode service_request array to string for save to db.
Use bellow code before the model save function :
$model->service_request = implode("," , $model->service_request);
$model->save();
Related
In the official docs I read:
Do bear in mind that virtual fields cannot be used in finds. If you want them to be part of JSON or array representations of your entities, see Exposing Virtual Fields.
It's not clear to me if the second sentence is in someway related to the first one - say as a workaround to overcome the limitation - or they are completely independent.
I mean: if I expose a Virtual Field then may I use it in a find statement?
Is there a way to include a virtual field in a query? Here a real example:
ItemOrdersTable.php:
$this->setTable('item_orders');
$this->setDisplayField('summary'); // virtual field
$this->setPrimaryKey('id');
Entity:
protected $_virtual = [
'summary'
];
protected function _getSummary()
{
return $this->name . ' ' . $this->description;
}
Usage in a Controller:
return TableRegistry::get('itemOrders')->find('list')->where(['order_id' => $id]);
Because I specified 'summary' as DisplayField, I'm expecting a key-value list of all records that meet the where clause, with the id as key and the summary virtual field as value. Because this doesn't happen (the returned object is null) I'm trying to understand if my code is wrong or I didn't read correctly the documentation as asked above.
Customize Key-Value Output:
https://book.cakephp.org/3.0/en/orm/retrieving-data-and-resultsets.html#customize-key-value-output
Update:
$results = TableRegistry::getTableLocator()->get('item_orders')
->find('list')
->where(['order_id' => $id]);
debug($results->toArray());
$this->set('orders', $results);
debug($orders); exit; <-- test results, and post in your question.
Hi I followed a tutorial to implement a friend system. It all works find, but I need to post other columns to the row that just the id's. How would I expand that.
This is the method that is accessed when the add friend button is clicked
public function getAdd($id){
$user = User::where('id', $id)->first();
//After passing all checks. Add other account
Auth::user()->addFriend($user);
echo "Sent";
}
AddTenancy Method
public function addFriend(User $user){
$this->friendsOf()->attach($user->id);
}
I assume the relationship is many-to-many between users. And you need to add additional data to the pivot.
Here's how you'd do that:
public function addFriend(User $user){
$this->friendsOf()->attach($user->id, ['another_col' => 'some data']);
}
Replace 'another_col' and some data with your column and your data. You can also add more than 1 column into the array.
I use belongstomany function to get the models and used withPivot() to get an extra column data in the pivot table. However, the withPivot() function will add the 2 foreign keys in the output json. I want to hide thses keys and only show the column I want to display.
The follwing is my response data
{"status_code":"1","next_page":"2","dataset":[{"id":"829","req_start_time":"2016-03-13 14:55:00","req_end_time":"2016-03-13 09:55:00","content":[{"name":"\u9752\u6912\u7092\u725b\u8089","price":"120","pic_url":"","detail":"\u8d85\u7ea7\u597d\u5403\u7684\u54df","pivot":{"waiter_request_id":"829","goods_id":"2","count":"2"}}
as you see the pivot json object contains two id keys.
how could i remove them from the object? or some other ways to solve this get the right way of this need?
thx in advance!
Now the question already upgraded!
How can I add this 'count' parameter of pivot in the object which belongs to 'content'
Finally,I figured out the right way to solve this problem. Follwing the code:
class Goods extends Model{
......
......
public function newPivot(Model $parent, array $attributes, $table, $exists)
{
$pivot = new Pivot($parent, $attributes, $table, $exists);
$pivot->addHidden(
array(
'waiter_request_id',
'goods_id'
)
);
return $pivot;
}
}
you can rewrite this method to provide a new pivot object to the Model in your 'belongsToMany'
I need to use article name on the url on Yii2 which is like http://example.com/article?id=1, just replace id=1 to article_name, like http://example.com/article/article_name or is it.
This is my controller code-
$model = Articles::find()->orderBy(['id' => SORT_DESC])->one();
View-
<?= Html::a('<b>Read more ...</b>', ['article-details','id' => $model->id], ['target'=>'_blank']) ?>
Thanks advance
You may use yii2 sluggable behavior Refer this.
There are few steps.
You must add the following urlManager rule :
'article/<slug>' => 'article/view',
You should build url in your view files like this :
\yii\helpers\Url::to(['article/view', 'slug'=>$model->title])
or
\yii\helpers\Url::to(['article/'.$model->title]);
And in your action
public function actionArticle($slug){
$model = Articles::find()->where(["title"=>$slug])->orderBy(['id' => SORT_DESC])->one();
//and other code
}
Also your article titles must be valid for url.You can do it easly by trimming whitespaces and so on But also you can add url some identification propery. or add column stored unique slugs for every article
You have two way
one change the related action in the controller changing id with name in the related function declaration
or declare a new action with the name as parameter
public function findModelName($article_name)
{
$model = Article::findOne(['name'=> $article_name]);
........ your related code
}
you can find the model by name this way
Article::findOne(['name'=> $article_name]);
The validation on Kohana ORM is done using rules
function rules()
{
return array(
'username' => array(
array('not_empty'),
array(array($this, 'availability')),
)
);
}
I'm struggling to validate a JSON encoded column using $_serialize_columns.
class Model_Admin extends ORM {
protected $_belongs_to = array();
protected $_has_many = array(
'plans' => array(),
'groups' => array(),
'transactions' => array(),
'logins' => array()
);
protected $_serialize_columns = array('data');
/**
* #param array $data
* #param Validation $validation
*
* #return bool
*/
public function data($data, $validation)
{
return
Validation::factory(json_decode($data, TRUE))
// ... rules ...
->check();
}
public function rules()
{
return array(
'data' => array(
array(array($this, 'data'), array(':value',':validation')
)
);
}
}
the array that gets encoded is:
array(
'name' => '',
'address' => '',
'phone' => '',
'postalcode' => ''
);
the data method receives the json encoded data, because the ORM runs the filters before doing the validation, so I need to convert it back to an associative array, then create a new validation object to check specifically for the content of that array. Because I can't merge Validation rules from another Validation instance
Updated Answer
The use of a second validation object is necessary since save() causes the internal model validation object to be checked. This means that rules added to the validation object being checked from a validation rule will be ignored (Validation->check() imports the rules into local scope before looping).
Since the data itself is technically another object (in the sense of object relationships, it has its own dataset that needs validation) the ideal solution would be to find a way to create a real model that saves the data.
There are numerous other benefits to saving data with proper database column definitions, not least if you need to perform data property lookups, make in-situ changes etc. (which would otherwise require unserializing the data column, potetnailly in all rows).
There are some alternatives, but they feel like kludges to me:
Create a model that represents the data object and add rules to it, using check() to validate the data (problem: will require a lot of maintenance, no real-world table means columns must be manually defined).
Set the data as real columns in the Admin model, and use a filter that will convert it into the data column on set (problem: again, must manually define the columns and exclude the additional columns from the save operation).
I hope this is of some use.
Original Answer
The Kohana ORM save() method permits the inclusion of an "extra" validation object, which is merged into the main ORM validation object namespace.
This is documented briefly here.
If I have understood correctly, I think you are looking to do something like this:
// another script, e.g., a controller
// Create the model
$admin = ORM::factory('Admin');
// $data = the data as an array, before serialization ...
$extra_validation = Validation::factory($data)
// add ->rule() calls here, but DO NOT chain ->check()
;
// Set $data in the model if it is going to be saved, e.g., $admin->data = $data;
// Set other data... e.g., $admin->foo = 'bar';
// Save the model
try {
$admin->save($extra_validation);
}
catch (ORM_Validation_Exception $e)
{
// Manipulate the exception result
}
While in this example you must still create another validation object, you are now able to catch all exceptions in a single block. I would recommend using var_dump() or similar on $e->errors() to check the namespace if you are using i18n messages to provide a human-readable error message. You should find that a namespace called "_external" has been created in the response.