Get attributes of model in init at behavior yii2 - yii2

Here is my code:
class CalculatedFieldsBehavior extends Behavior {
public $calcFields = array();
public function events() {
return [
ActiveRecord::EVENT_INIT => 'init',
];
}
public function init() {
foreach ($this->owner->attributes() as $attribute) {
if (strpos($attribute, 'calc_')) {
if (!is_function(get_parent_class()::$set . \yii\helpers\camelize($attribute))) {
throw Exception("Function to set value of calc field '" . $attribute . "' not defined.");
}
$calcFields[] = $attribute;
}
}
if (!($this->owner->hasAttribute('isCalcValueSet'))) {
throw Exception("This table is missing a field for isCalcValueSet");
}
parent::init();
}
}
And give this error:
"name": "Exception",
"message": "Call to a member function attributes() on null",
"code": 0,
"type": "Error",
"file": "D:\\xampp\\htdocs\\backoffice\\common\\models\\CalculatedFieldsBehavior.php",
"line": 25,

$owner is not available in init(). It is set in attach(). Usually workflow looks like this:
$behavior = new MyBehavior(); // init() is called here
$behavior->attach($owner); // owner is set here
You should probably overwrite attach() in your case:
public function attach($owner) {
foreach ($owner->attributes() as $attribute) {
if (strpos($attribute, 'calc_')) {
if (!is_function(get_parent_class()::$set . \yii\helpers\camelize($attribute))) {
throw Exception("Function to set value of calc field '" . $attribute . "' not defined.");
}
$calcFields[] = $attribute;
}
}
if (!($owner->hasAttribute('isCalcValueSet'))) {
throw Exception("This table is missing a field for isCalcValueSet");
}
parent::attach($owner);
}

Related

Newtonsoft.json SelectToken Replace differs from SelectTokens Replace in foreach with a NullReferenceException

Hope anybody could guide me here. I spend some hours on it and can't understand what's going on.
Mission: Replace a json element by a jsonpath search tag. (sort of $ref feature)
In my code example below i want to replace the value of DataReaderUser by a value found by the json path search $.UsersAndGroups.Users[?(#.Name == 'OMDASAccountUser')].Username . In this case it should result in the value "contoso\SVCSCOM-DO-OMDAS"
The code below works as expected.. the issue is below this code ..
https://dotnetfiddle.net/gEjggK
using System;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
string json = #"{
""SQLServer"": {
""SQLReportingServices"": {
""AccountSettings"": {
""DataReaderUser"": {""$JsonPath"": ""$.UsersAndGroups.Users[?(#.Name == 'OMDASAccountUser')].Username""},
}
}
},
""UsersAndGroups"": {
""Users"": [
{
""Name"": ""OMActionAccountUser"",
""Username"": ""contoso\\SVCSCOM-DO-OMDAS"",
},
{
""Name"": ""OMDASAccountUser"",
""Username"": ""contoso\\SVCSCOM-DO-OMDAS"",
}
]
}
}";
JObject jo = JObject.Parse(json);
var JsonPath = jo.SelectToken("..$JsonPath");
JsonPath.Parent.Parent.Replace(jo.SelectToken(JsonPath.ToString()));
Console.WriteLine(jo.ToString());
}
}
The output will be :
{
"SQLServer": {
"SQLReportingServices": {
"AccountSettings": {
"DataReaderUser": "contoso\\SVCSCOM-DO-OMDAS"
}
}
},
"UsersAndGroups": {
"Users": [
{
"Name": "OMActionAccountUser",
"Username": "contoso\\SVCSCOM-DO-OMDAS"
},
{
"Name": "OMDASAccountUser",
"Username": "contoso\\SVCSCOM-DO-OMDAS"
}
]
}
}
Now the issue:
I want to do the same for all possible jsonpaths refers. So i use the SelectTokens and an foreach . But it looks like the behavior is different , the parents are null.
https://dotnetfiddle.net/lZW3XP
using System;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
string json = #"{
""SQLServer"": {
""SQLReportingServices"": {
""AccountSettings"": {
""DataReaderUser"": {""$JsonPath"": ""$.UsersAndGroups.Users[?(#.Name == 'OMDASAccountUser')].Username""},
}
}
},
""UsersAndGroups"": {
""Users"": [
{
""Name"": ""OMActionAccountUser"",
""Username"": ""contoso\\SVCSCOM-DO-OMDAS"",
},
{
""Name"": ""OMDASAccountUser"",
""Username"": ""contoso\\SVCSCOM-DO-OMDAS"",
}
]
}
}";
JObject jo = JObject.Parse(json);
var JsonPaths = jo.SelectTokens("..$JsonPath");
foreach (var JsonPath in JsonPaths )
{
JsonPath.Parent.Parent.Replace(jo.SelectToken(JsonPath.ToString()));
}
Console.WriteLine(jo.ToString());
}
}
And the output:
Run-time exception (line 34): Object reference not set to an instance of an object.
Stack Trace:
[System.NullReferenceException: Object reference not set to an instance of an object.]
at Newtonsoft.Json.Linq.JsonPath.PathFilter.GetNextScanValue(JToken originalParent, JToken container, JToken value)
at Newtonsoft.Json.Linq.JsonPath.ScanFilter.<ExecuteFilter>d__4.MoveNext()
at Program.Main() :line 34
would be great to get some directions since i am spinning my head here.
michel
SelectTokens uses lazy evaluation and if you modify the token while enumerating all matches it can break in unexpected ways. A simple fix is to add ToArray() to force eager evaluation:
var JsonPaths = jo.SelectTokens("..$JsonPath").ToArray();

How to use Yii2 Queue::EVENT_AFTER_ERROR event

I'm using Yii2 Queue extension.
I want to add error handler after triggering error event in job.
This is my model:
namespace app\models;
use Yii;
use yii\base\BaseObject;
use yii\queue\JobInterface;
use yii\queue\Queue;
class AddTransaction extends BaseObject implements JobInterface
{
public function execute($queue)
{
$test = new League();
$test->title_fa = 'تست';
$test->title_en = 'test';
$test->status = 1;
$test->country_id = 3;
$test->created = time();
$test->save();
}
}
This is my action:
public function actionTest()
{
if (Yii::$app->queue->delay(5)->push(new AddTransaction())) {
echo "ok";
} else {
echo "error";
}
}
Where use this code?
Yii::$app->queue->on(Queue::EVENT_AFTER_ERROR, function (ErrorEvent $event) {
if ($event->job instanceof SomeJob) {
$event->retry = ($event->attempt < 5) && ($event->error instanceof TemporaryException);
}
});
You may add this to queue config array:
'components' => [
// ...
'queue' => [
// ...
'on afterError' => function (ExecEvent $event) {
if ($event->job instanceof SomeJob) {
$event->retry = ($event->attempt < 5) && ($event->error instanceof TemporaryException);
}
},
],
],
In advanced template you have bootstrap.php config file there you may subscribe to events and so on.
This is one of adopted examples from docs
Event::on(Queue::className(), Queue::EVENT_AFTER_ERROR, function ($event) {
Yii::debug(get_class($event->sender) . ' is error');
});

Laravel and vue.js validation

From my Laravel api I receive the following validation errors within json:
{
"error": {
"billabletime": [
"The billabletime field is required."
],
"time": [
"time bust be a integer."
]
}
}
So how would I show them in vue.js? Right now I've this but that's obviously not working:
showError (message) {
swal({
title: "Fout",
text: message.error,
type: "error",
timer: 2000,
showConfirmButton: false
});
}
Like this:
var errorString = '';
if (message.hasOwnProperty('error')) {
for(var prop in message.error) {
if (Array.isArray(prop)) {
for (var msg in prop) {
errorString += prop[msg] . '<br/>';
}
} else {
errorString += message.error[prop] . '<br/>';
}
}
}
Something simple like this should give you the desired result. Not necessary to know index names.
Edit added functionality to handle stirng/array

Error Rule not found on RBAC DbManager Yii2

I followed this guide (http://www.yiiframework.com/doc-2.0/guide-security-authorization.html) but still got an error.
I have created auth_item, auth_item_chid, auth_assignment, and auth_rule Table
When i add this line to my controller
if (\Yii::$app->user->can('createPost')) { //mycode ... }
i got error -> Rule not found: author
protected function executeRule($user, $item, $params)
{
if ($item->ruleName === null) {
return true;
}
$rule = $this->getRule($item->ruleName);
if ($rule instanceof Rule) {
return $rule->execute($user, $item, $params);
} else {
throw new InvalidConfigException("Rule not found: {$item->ruleName}");
}
}
I have assigned the user with a role in auth_item table, the auth_item already have auth_item_chid.
On Yii2 all auth_item should set with rule_name. Thats the different with the previous version.
You can extend DbManager for fix error
<?php
namespace app\components;
use yii\base\InvalidConfigException;
use yii\rbac\Rule;
class DbManager extends \yii\rbac\DbManager
{
protected function executeRule($user, $item, $params)
{
if (empty($item->ruleName)) {
return true;
}
return parent::executeRule($user, $item, $params);
}
}
And change config/web.php like
'authManager' => [
'class' => 'app\components\DbManager'
],

Laravel error:: Illegal string offset 'category_name'

I'm trying to create an admin side form. Here i'm trying to select data from the database. Also i want to display it. But for some reason it's not working. Here's my controller code,
public function save()
{
if (Input::has('save'))
{
$rules = array('category_name' => 'required|min:1|max:50', 'parent_category' => 'required');
$input = Input::all();
$messages = array('category_name.required' =>'Please enter the category name.', 'category_name.min' => 'Category name must be more than 4 characters', 'category_name.max' =>'Category name must not be more than 15 characters!!!', 'parent_category.required' => 'Please Select Parent Category.',);
$validator = Validator::make($input, $rules, $messages);
if ($validator->fails())
{
return Redirect::to('admin/category/add')->withErrors($validator)->withInput($input);
}
else
{
$insert_db = CategoryModel::insert($input);
$selected_category = CategoryModel::select($input['category_name']);
}
}
}
and my CategoryModel.php is following.
public static function insert($values)
{
$insert = DB::table('add_category')->insert(array('category_name'=>$values['category_name'], 'parent_category'=>$values['parent_category']));
if(isset($insert))
{
echo 'inserted successfully';
}
else
{
echo 'Failed';
}
}
public static function select($values)
{
$insert = DB::table('add_category')->where('category_name' . '=' . $values['category_name']);
}