I want to save and update data at once. In saveMany function.
I have data like
[
[
'id'=>1,
'name' => 'test1'
],
[
'name' => 'test2'
]
]
if id is there then I need to update the record. Else i need to add the record. How can I achieve this in cakephp 3.
Yes, it will be worked if you receive data in your post request in same manner or set data in array in same manner.
$data=[
[
'id'=>1,
'name' => 'test1'
],
[
'name' => 'test2'
]
];
// In a controller.
$articles = TableRegistry::get('Articles');
$entities = $articles->newEntities($data);
// if you want to follow transaction manner
$articles->connection()->transactional(function () use ($articles, $entities) {
foreach ($entities as $entity) {
$articles->save($entity, ['atomic' => false]);
}
});
// without transaction manner
foreach ($entities as $entity) {
$articles->save($entity);
}
Related
I have a requirement to configure ownership for priceList entities. To approach this I created a migration to add the required fields:
$this->extendExtension->addManyToOneRelation(
$schema,
$table,
'organization',
$organizationTable,
'name',
[
'extend' => [
'is_extend' => true,
'owner' => ExtendScope::OWNER_SYSTEM,
'without_default' => true,
]
]);
$this->extendExtension->addManyToOneRelation(
$schema,
$table,
'owner',
$businessTable,
'name',
[
'extend' => [
'is_extend' => true,
'owner' => ExtendScope::OWNER_SYSTEM,
'without_default' => true,
]
]
);
Then updated entity configuration information with:
$params = [
"owner_type" => "BUSINESS_UNIT",
"owner_field_name" => "owner",
"owner_column_name" => "owner_id",
"organization_field_name" => "organization",
"organization_column_name" => "organization_id"
];
foreach($params as $code => $value) {
$queries->addPostQuery(
new UpdateEntityConfigEntityValueQuery(
PriceList::class,
'ownership',
$code,
$value
)
);
}
Migration processed without issues but for the data grid on the priceList index page error occurred.
An exception occurred while executing 'SELECT count(o0_.id) AS sclr_0 FROM oro_price_list o0_ WHERE o0_. = 1'
It looks like the data grid couldn't reach the organization name to handle the pagination query. Data grid unmodified grid from ORO 4.1 EE
Everything works fine if ownership configuration updated via SetOwnershipTypeQuery intead of UpdateEntityConfigEntityValueQuery
$queries->addQuery(
new SetOwnershipTypeQuery(
PriceList::class,
[
'owner_type' => 'BUSINESS_UNIT',
'owner_field_name' => 'owner',
'owner_column_name' => 'owner_id',
'organization_field_name' => 'organization',
'organization_column_name' => 'organization_id'
]
)
);
I've created a list which is fully populated with records from database. I'd like to add a button 'delete' in order to delete records on demand. The button appears, but whenever it makes a request, it does not have an ID of the record I want to delete. The URL looks like this:
controller=AdminModules&configure=estimateddelivery&=&deleteestimateddelivery&token=6d1625ddf520e0bf8d2c43bea84f21d3
There is a &=& which if I understand correctly should be populated with something like &id=10&. I am not sure what the problem is or where to look at. I've check code examples of similar functionalities and it looks like I am doing everything the same way.
public function renderList()
{
$this->$fields_list = [
'id_estimateddelivery' => [
'title' => $this->l('ID'),
'type' =>'text',
],
'from' => [
'title' => $this->l('Delivery period from')
],
'to' => [
'title' => $this->l('Delivery period to')
],
'countries' => [
'title' => $this->l('Countries applicable'),
'type' => 'text'
]
];
$helper = new HelperList();
$helper->module = $this;
$helper->shopLinkType = '';
$helper->simple_header = true;
$helper->idientifier = 'id_estimateddelivery';
$helper->actions = [
'delete'
];
$helper->show_toolbar = false;
$helper->title = $this->l('List of created estimated deliveries');
$helper->table = $this->name;
$helper->token = Tools::getAdminTokenLite('AdminModules');
$helper->currentIndex = AdminController::$currentIndex . '&configure=' . $this->name;
return $helper->generateList($this->getEstimatedDeliveries(), $this->$fields_list);
}
public function deleteEstimatedDelivery()
{
return Db::getInstance()->execute('DELETE FROM '. _DB_PREFIX_ .'estimateddelivery WHERE `id_estimateddelivery` = '. (int)Tools::getValue('id_estimateddelivery'));
}
else if(Tools::isSubmit('delete' . $this->name))
{
if(!$this->deleteEstimatedDelivery())
$output . $this->displayError($this->l('An error occured during link deletion'));
else
$output . $this->displayConfirmation($this->l('The estimated delivery has been deleted'));
}
Even though there was no error message, the code line: $helper->idientifier = 'id_estimateddelivery'; had a typo. Should have been identifier.
I have an array as follows:
[
0 => [
'name' => 'CARD'
'id' => '0'
]
1 => [
'name' => 'MOBILE'
'id' => '1'
]
2 => [
'name' => 'GIFT'
'id' => '2'
]
]
I want to change the key id to type in all the array. Is there a way to do this in Yii2 using ArrayHelper?
You can use getColumn() for this:
$result = ArrayHelper::getColumn($array, function ($data) {
return [
'name' => $data['name'],
'type' => $data['id'],
];
});
But it will not really differ from array_map() or simple foreach.
There is not an array helper for this but you could do this with a php foreach
foreach ($myArray as $key => $value) {
$myArray[$key]['type'] = $value['id'];
unset($myArray[$key]['id']);
}
I am new to yii2 and I don't exactly know how to apply same rules of insert into update. Here is my rules for insert and I want all rules to effect on update too.
public $tag;
public function rules()
{
return [
[['user_id', 'name', 'address', 'state'], 'required'],
[['user_id'], 'integer'],
[['tag'], 'safe'],
[['name'], 'string', 'max' => 30],
[['address'], 'string', 'max' => 250],
[['state'], 'string', 'max' => 255],
];
}
Adding 'on' => 'update' doesn't effect in my code. Sorry for my english. Thanks.
The default rules are applied in the creation and update, you only have to create new rules if you want different behaviors between update and create.
To apply the rules just make a $model->validate() to check the rules, see this example of the documentation of yii2
$model->load(\Yii::$app->request->post());
if ($model->validate()) {
// all inputs are valid
} else {
// validation failed: $errors is an array containing error messages
$errors = $model->errors;
}
You can add validation rules to yii model like this
public function rules(){
return [
[['boolean_var'],'boolean'],
[[ 'range_in_string'],'required'],
[['default_value'],'default','value'=>'DEFAULT VALUE'],
[['integer_var'],'integer'],
[['double_var'],'double'],
[['number_min'],'number','min'=>10],
[['number_max'],'number','max'=>100],
[['number_min_max'],'number','min'=>10,'max'=>100],
[['file_image'],'image'],
[['file_var'],'file','types'=>['gif','jpg']],
[['date_var'],'date', 'format'=>'d-m-yy'],
[['min_string'],'string','min'=>10],
[['max_string'],'string','max'=>10],
[['min_max_string'],'string','min'=>5,'max'=>10],
['min_max_string2', 'string', 'length' => [4, 10]],
['email_var','email'],
['url_var','url'],
[['unique_var'],'unique'],
[['filter_trim'],'filter','filter'=>'trim'],
[['filter_trim'],'filter','filter'=>'strtolower'],
['filter_custom_function', 'filter', 'filter' => function ($value) {
// your concept
if($value=='')
return '';
return 'Value Changed';}],
['range_in_min_max', 'in','range'=>range(5,20)],
['range_in','in','range'=>['en','fr','zn'],'strict'=>false], //strict false
['range_in_string','in','range'=>['EN','FR','ZN'],'strict'=>true],
['custom_validation','custom_function_validation'],
[['passwordConfirm'], 'compare', 'compareAttribute' => 'password'],
[['password','date_var'],'safe'],
];
}
if you need to trigger only when updating but not creating, you can add a scenario like this
public function rules()
{
return [
// username, email and password are all required in "update" scenario
[['username', 'email', 'password'], 'required', 'on' => 'update'],
// username and password are required in "login" scenario
[['username', 'password'], 'required', 'on' => 'login'],
];
}
and in your action before calling validate add the scenario
// scenario is set as a property
$model = new User;
$model->scenario = 'update';
I am having a trouble with login part.
I read this topic : http://www.yiiframework.com/wiki/771/rbac-super-simple-with-admin-and-user/ .
Then i follow its steps, but in step 6. it only configs for just one Controller. I have a Module called Admin with many controllers in it and i don't know how to apply this access control to the whole module. Can anyone help me ?
Sorry for my bad English.
You can create AdminController class, which will extends yii\web\Controller where you define your access rules in behaviors method and make other module controllers extend your AdminController and override behaviors method like this:
public function behaviors()
{
return \yii\helpers\ArrayHelper::merge(parent::behaviors(), [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
],
],
]);
}
Here parent::behaviors() are behaviors from AdminController which define default access rules, and you merge them with specific behaviors in your child controller. It gives you flexibility to override some access rules if you need.
I can propose a variation of the method from the article that you mentioned.
Make first 2 steps as it was described and then do the following:
1. Add the field role to User model and evaluate it with thevalue of one of the constants from the article's example (User::ROLE_ADMIN or User::ROLE_USER)
2. Override the yii\web\User->can()
public function can($permissionName, $params = [], $allowCaching = true)
{
/** #var \app\models\User $user */
$user = $this->identity;
$access = false;
do {
if (\Yii::$app->user->isGuest) {
break;
}
if ($user->role === \common\models\User::ROLE_ADMIN) {
$access = true;
break;
}
if (is_array($permissionName)) {
$access = in_array($user->role, $permissionName);
} else {
$access = $permissionName === $user->role;
}
} while (false);
return $access;
}
So now you can check user's role like this:
\Yii::$app->user->can(User::ROLE_USER)
3. You say:
i don't know how to apply this access control to the whole module.
Then open your module class and add the following to the behaviors() method:
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
'rules' => [
[
'allow' => true,
'roles' => [User::ROLE_ADMIN]
]
]
]
];
}
In this example we grant access to ROLE_ADMIN to all actions of all controllers of your module.
That's it.
Make a custom model AccessRules.php as shown below:
<?php
namespace app\models;
class AccessRules extends \yii\filters\AccessRule
{
/**
* #inheritdoc
*/
protected function matchRole($user)
{
if (empty($this->roles)) {
return true;
}
foreach ($this->roles as $role) {
if ($role === '?') {
if ($user->getIsGuest()) {
return true;
}
} elseif ($role === '#') {
if (!$user->getIsGuest()) {
return true;
}
// Check if the user is logged in, and the roles match
} elseif (!$user->getIsGuest() && (int)$role === $user->identity->user_role) {
return true;
}
}
return false;
}
}
?>
Now open your site controller and add the following code in fuction behavior part:
use app\models\AccessRules;
public function behaviors()
{
return [
'access' => [
'class' => AccessControl::className(),
// We will override the default rule config with the new AccessRule class
'ruleConfig' => [
'class' => AccessRules::className(),
],
'only' => ['create', 'update', 'delete','index'],
'rules' => [
[
'actions' => ['create', 'update', 'delete','index'],
'allow' => true,
// Allow admin to create
'roles' => [
'1'
],
]
],
],
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'logout' => ['post'],
],
],
];
}
According to The Yii2 Guide
"ACF is an action filter that can be used in a controller or a module" in the same way.
Just add below code in controller which you want to restrict functionality
'access' => [
'class' => AccessControl::className(),
'rules' =>
[
[
'actions' => ['index','view'],
'allow' => true,
'roles' => ['#']
],
[
'actions' => ['create','update','delete'],
'allow' => true,
'roles' => ['#'],
'matchCallback' => function ($rule, $action)
{
return Admin::isUserAdmin(Yii::$app->user->identity->username);
}
],
],
],