I am using Ichikawa CakePHP MongoDB plugin. I have a problem in using unset in it. I have tried the command in shell:
db.patents.update({}, {$unset : {"lv.2" : 1 }},{'multi':true})
db.patents.update({},{$pull:{pid:"2"}},{'multi':true})
These are working fine.
But when I am converting them to CakePHP command as follows:
$this->Detail->updateAll(array('$unset'=>array('lv.2'=>1,array('multi'=>true))));
Then it doesn't work and gives error:
MongoCollection::update(): expects parameter 1 to be an array or object, boolean given
Can anyone help me to figure out the problem.
Thanks.
There are no conditions
The error message means that the query being generated is the equivalent of:
db.details.update(true
This can be confirmed by checking the query log (easy if you're using debug kit).
How is that happening
The second parameter for model updateAll is missing, which means it will have the default:
public function updateAll($fields, $conditions = true) {
^
return $this->getDataSource()->update($this, $fields, null, $conditions);
}
Therefore in the mongodb datasource class - the conditions passed are true:
public function updateAll(&$Model, $fields = null, $conditions = null) {
^
As a consequence, the resultant update statement has true as the first parameter, not an array.
Correct syntax
The correct syntax for such a query is:
$this->Detail->updateAll(
array('$unset'=>array('lv.2'=>1))
array() # <- do not omit this
);
Note that it's not necessary to specify 'multi'=>true as the datasource does that for you, especially not in the fields argument.
Related
I am having trouble to dynamically modify field in my form using DataMapper and EventSubscriber.
Here is my form:
A select field
A field which will be modified by the select field above.
I am using an EventSubscriber to dynamically modify my form using AJAX.
And a DataMapper to map my Value Object to the form and vice-versa.
So when i do that:
$moneyForm = $this->createForm(MoneyType::class);
Everything is working. But when i pass my Value Object as data class:
$money = new Money(199, 'USD');
$moneyForm = $this->createForm(MoneyType::class, $money);
I got an error here:
public function mapDataToForms($viewData, $forms)
{
$forms = iterator_to_array($forms);
$forms['money']->setData($viewData ? $viewData->money() : 0);
$forms['currency']->setData($viewData ? $viewData->currency() : 'USD');
}
This error says that: Notice: Undefined index:.
It seems like the form has been replaced by a new one and i don't understand it.
I don't know why when i use a data mapper alone, or event subscriber alone everything is working.
But when i try to mix, both of them i got this error.
Does anyone have a clue of what's going on here?
Thank you
I am new to Scala. Writing my first application.
I have defined my proto file with fields email_id and phone_number which is request definition for grpc call
I can access values by dot operator like params.emailId
Now what I am trying to do is I have one array of mandatory fields. I want to check the values for those fields defined in an array with input request parameters.
How can i access this params.{field name from array} to check for not empty values.
Getting error for below code with :
val mandatoryFields = Array("emailId","phoneNumber")
println(params.emailId) //works
for (fields <- mandatoryFields) {
println(fields)
println(params.fields) // getting error
}
It has function 'in.getFieldByNumber()' where you can fetch value by index location, is there any function available like getFieldByName() or something like that.
Although it's been a long from the question date, I don't think it is answerless. Actually, I have one:
Using toPMessage method, you'll have your protobuffer case class as an instance of PMessage object. Then you could retrieve the Map[FieldDescriptor, PValue]. Finding field values by name would be like:
val fieldDescriptorPValueMap: Map[FieldDescriptor, PValue] = params.toPMessage.value
mandatoryFields.foreach(fieldName=>{
println(
fieldDescriptorPValueMap
.filter(entry => fieldName == entry._1.name)
.values
.head.as[String]
)
})
I am using Groovy Sql in Grails with named parameters to get results from a Postgres DB. My statement is generated dynamically, i.e. concatenated to become the final statement, with the params being added to a map as I go along.
sqlWhere += " AND bar = :namedParam1"
paramsMap.namedParam1 = "blah"
For readability, I am using the groovy string syntax which allows me to write my sql statement over multiple lines, like this:
sql = """
SELECT *
FROM foo
WHERE 1=1
${sqlWhere}
"""
The expression is evaluated as a string containing the linebreaks as \n:
SELECT *\n ...
This is not a problem when I pass params like this
results = sql.rows(sqlString, paramsMap)
but it does become one if paramsMap is empty (which happens since AND bar = :namedParam1 is not always concatenated into the query). I then get an error
org.postgresql.util.PSQLException: No hstore extension installed
which does not really seem to relate to the true nature of the problem. I have for now fixed this with an if...else
if (sqlQuery.params.size() > 0) {
results = sql.rows(sqlString, paramsMap)
} else {
results = sql.rows(sqlString.replace('\n',' '))
}
But this seems a bit weird (especially since it does not work if I use the replace in the if-branch as well).
My question is: why do I really get this error message and is there a better way to prevent it from occuring?
It's certainly a bug in groovy.sql.SQL implementation. The method rows() can't deal with an empty map passed as params. As a workaround, you can test for it and pass an empty list instead.
def paramsMap = [:]
...
if (paramsMap.isEmpty())
paramsMap= []
Issue created at https://issues.apache.org/jira/browse/GROOVY-8082
Before anything I am aware of the multiple questions asked concerning this exception. I have looked through them but have not found an answer for my particular problem. Most of the questions use the Zend_Db_Table::getDefaultAdapter(); , and I am not using that. Instead I am using an Application_Model_DbTable_Name and am left wondering if it´s possible to do so.
Also, I do have access since that´s the first thing I checked when I saw the error. The database is local and I access it with the same user/password through MySqlWorkBench.
My goal is to delete a row when two columns meet the criteria set in the controller action, like so:
public function deleteAction(){
$request = $this->getRequest();
$this->_validateDigit($request->getParam('id'));
// _validateDigit(..) checks that the variable is numeric and if it´s not it redirects to
// an error page
$db = new Application_Model_DbTable_BecasPerfiles();
$select = $db->select();
$select->where('unidad=?', $this->_getUnit())
->where('id=?', (int) $request->getParam('id'));
$db->delete($select->getPart(Zend_Db_Select::WHERE));
$this->_redirect('/profile/view-profiles/unit/'.$this->_getUnit());
}
private function _getUnit()
{
return Zend_Registry::getInstance()['session']->unit;
//unit is nothing but a string
}
Here is my DbTable class (real simple):
class Application_Model_DbTable_BecasPerfiles extends Zend_Db_Table_Abstract
{
protected $_name = 'becas_perfiles';
}
Here is the error that spits out:
Message: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in
your SQL syntax; check the manual that corresponds to your MySQL server version for
the right syntax to use near 'AND (id=7))' at line 1
Here is what calls my attention AND (id=7)), see the extra parenthesis? where is that coming from?
Here is the result of var_dump($select->getPart(Zend_Db_Select::WHERE));
array(2) { [0]=> string(33) "(unidad='Galería de Arte ULPGC')" [1]=> string(10) "AND (id=7)" }
Just for the fun of it, I tried switching the order of the where clause:
$select->where('id=?', (int) $request->getParam('id'))
->where('unidad=?', $this->_getUnit());
Here is the output:
Message: SQLSTATE[42000]: ...
syntax to use near 'AND (unidad='Galería de Arte ULPGC'))' at line 1
There it is again, AND (unidad='Galería de Arte ULPGC')) that second parenthesis. I don´t really know if that´s the problem (but I figure it is because otherwise I don´t know what could posssibly be wrong).
I tried just using one where condition (like id), and it deleted just fine. I´d really appreciate your help, thank you!
The problem here is that there is a mismatch between what getPart() returns and what delete() expects.
As you already pointed out, var_dump($select->getPart(Zend_Db_Select::WHERE)); also returns the logical operators in the where statement, but the delete() operator either expects an array in the form "field => value" or a string containing the full where clause.
So the simplest (untested) approach to fix your problem would be to pass $db->delete(implode(' ', $select->getPart(Zend_Db_Select::WHERE))); so that delete() receives a fully qualified where clause as string instead of an array it cannot handle.
I'm trying to do this with mongodbauthmanager. I'm follow step by step in Usage section but finally i'm getting PHP warning: Illegal offset type. I had posted this question at Yii Extension before clone to SO:
Please tell me what is wrong?
1// Config
'authManager'=>array(
'class' =>'CMongoDbAuthManager',
'showErrors' => true,
),
2// Create auth items in db
$auth = new CMongoDbAuthManager();
$bizRule = 'return Yii::app()->user->id==$params["User"]->_id;';
$auth->createTask('updateSelf', 'update own information', $bizRule);
//I had tried with $auth->createOperation() but they has the same error
$role = $auth->createRole('user');
$role->addChild('updateSelf');
$auth->save();
and here is result in db
result in db http://i.minus.com/iIpXoBlDxaEfo.png
**3// Checking access in controller ** - UPDATE CODE AND ERROR
public function actionUpdate($id)
{
$model=$this->loadModel($id);
$params = array('User'=>$model);
if (!Yii::app()->user->checkAccess('updateSelf', Yii::app()->user->id,$params) )
{
throw new CHttpException(403, 'You are not authorized to perform this action');
}
//another statement ...
}
4// Getting error:
Fatal error : Cannot use object of type MongoId as array in F:\Data\03. Lab\www\yii\framework\web\auth\CAuthManager.php(150) : eval()'d code on line 1
RESOLVED PROBLEM
Base-on the answer of #Willem Renzema, I resolve my problem. Now, I update here and hope it useful for someone have this error.
0// First, config authManager with defaultRoles
'authManager'=>array(
'class'=>'CMongoDbAuthManager',
'showErrors' => true,
'defaultRoles'=> array('user'),//important, this line help we don't need assign role for every user manually
),
1// Fix save id in UserIdentity class
class UserIdentity extends CUserIdentity
{
private $_id;
//...
public function authenticate()
{
//...
$this->_id = (string)$user->_id;//force $this save _id by string, not MongoId object
//...
}
//...
}
2// Fix $bizrule in authe items
($bizrule will run by eval() in checkAccess)
//use _id as string, not MongoId object
$bizRule = 'return Yii::app()->user->id==(string)$params["User"]->_id;';
3// And user checkAccess to authorization
public function actionUpdate($id){
/**
* #var User $model
*/
$model=$this->loadModel($id);
$params = array('User'=>$model);
if (!Yii::app()->user->checkAccess('updateSelf', $params) )
{
throw new CHttpException(403, 'You are not authorized to perform this action');
}
//...
}
4// Done, now we can use checkAccess :D
First off, your original use of checkAccess was correct. Using Yii::app()->user->checkAccess() you are using the following definition:
http://www.yiiframework.com/doc/api/1.1/CWebUser#checkAccess-detail
Now, CWebUser's implementation of checkAccess calls CPHPAuthManager's implementation, which is where you encountered your problem with an illegal offset type.
http://www.yiiframework.com/doc/api/1.1/CPhpAuthManager#checkAccess-detail
An Illegal offset type means you are attempting to access an array element by specifying its key (also known as: offset) with a value that doesn't work as a key. This could be another array, an object, null, or possibly something else.
Your stack trace posted on the extensions page reveals that the following line gives the problem:
if(isset($this->_assignments[$userId][$itemName]))
So we have two possibilities for the illegal offset: $userId and $itemName.
Since $itemName is clearly a string, the problem must be with $userId.
(As a side note, the fact that your stack trace revealed surrounding code of this error also revealed that, at least for CPHPAuthManager, you are using a version of Yii that is prior to 1.1.11. Observe that lines 73 and 74 of https://github.com/yiisoft/yii/blob/1.1.11/framework/web/auth/CPhpAuthManager.php do not exist in your file's code.)
At this point I would have guessed that the problem is that the specified user is not logged in, and so Yii::app()->user->id is returning null. However, the new error you encountered when placing Yii::app()->user->id as the 2nd parameter of checkAccess reveals something else.
Since the 2nd parameter is in fact what should be the $params array that appears in your bizRule. Based on the error message, this means that Yii::app()->user->id is returning a mondoId type object.
I was unfamiliar with this type of object, so looked it up:
http://php.net/manual/en/class.mongoid.php
Long story short, you need to force Yii::app()->user->id to return the string value equivalent of this mondoId object. This likely set in your UserIdentity class in the components folder. To force it to be a string, simply place (string) to force a type conversion.
Example:
$this->_id = (string)$User->_id;
Your exact code will vary, based on what is in your UserIdentity class.
Then, restore your checkAccess to the signature you had before, and it should eliminate the Illegal offset error you encountered originally.
Note however that I have not used this extension, and while performing the following actions should fix this issue, it may cause new issues if the extension relies on the fact that Yii::app()->user->id is a mondoId object, and not a string.