Zend_Session: unserialize session data - zend-framework

I'm using session SaveHandler to persist session data in the database.
Sample session_data column from the database:
Messenger|a:1:{s:13:"page_messages";a:0:{}}userSession|a:1:{s:7:"referer";s:32:"http://cms.dev/user/profile/view";}Zend_Auth|a:1:{s:7:"storage";O:19:"User_Model_Identity":3:{s:2:"id";s:1:"1";s:8:"username";s:13:"administrator";s:4:"slug";s:13:"administrator";}}
I want to delete Zend_Auth object from this session data.
How can I unserialize those objects and remove object I need?
I suspect, that I don't have to write my custom parser, that Zend_Session already has a method to do this. I have tried different combinations of unserialize but it still returns false.
I'm using autoloader from ZF 1.10.2 and Doctrine 1.2

The code below will work, it is not mine, but in essence what it does is split the session string apart using the pipe as a delimiter, the unserialize the split chunks individually.
The problem is that the build in unserialize function in php doesn't understand the concatenated serialization.
function unserialize_session_data( $serialized_string ) {
$variables = array();
$a = preg_split("/(\w+)\|/", $serialized_string, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
for($i=0;$i<count($a);$i=$i+2){
$variables[$a[$i]] = unserialize($a[$i+1]);
}
return($variables);
}

Related

how to ignore extra fields when storing prisma data?

I'm loading some data from a CSV file that has some extra notes fields that I don't want in the DB. Is there an option to just ignore extra fields when storing to the DB?
I think mongoose did this by default - which does have a downside that stuff goes missing without warning if your schema is wrong but... thats what i want in this case.
Otherwise what is a way to reflect and get the schema so I can remove extra fields from the data manually?
I'm getting this error on .create
Unknown arg `notes` in data.notes for type WalletCreateInput.
Did you mean `name`?
Available args:
...
It's not allowed to add extra fields while interacting with Prisma Query.
The current behaviour is intentional and it throws the error as an extra validation layer to make sure you're passing the right data.
There is a feature request that discusses allowing extra fields while interacting with Query.
As of now, destructuring the fields which are necessary and passing only the required fields is the only option.
Late to the party, but there is a way around this.
If you use the "fieldReference" preview feature:
generator client {
provider = "prisma-client-js"
previewFeatures = ["fieldReference"]
}
You can then create the following to strip out any extra keys.
function stripPrisma<T extends {}>(input: {fields:{}},data: T) : T {
let validKeys = Object.keys(input.fields);
let dataCopy: any = {...data};
for(let key of Object.keys(data)) {
if(!(validKeys.includes(key))) {
delete dataCopy[key];
}
}
return dataCopy as T;
}
And use it like this
data = stripPrisma(prisma.myTable, data);
prisma.myTable.create({data:data});
It is not perfect, since it will only be able to use "checked input", meaning you can only use the foreign key in your input and not the foreign object.

Validating array input in AppSync Resolver Template

I have a query in my aws app-sync:
input TestingInput {
user_ids: [String]!
}
Now, I need to do 2 different validations here:
Validate that the user_ids is an array of strings.
Validate that all user_ids exists in database.
For 1, I can use $util.isList(), but it cannot verify the if there is empty string of not. Is there any way we can filter out the empty string from array and then check the length of array?
For 2, no idea as of right now
Velocity scripting has access to some Java API. In this case, they're lists, and strings. However, I'm not sure what Java version AppSync supports. From AWS documentation, it's being linked to Java SE 6. Go back to your problem, it's done by having a new list, and add non-empty ids into it.
#set( $nonEmptyUserIds = [] )
#foreach( $userId in $userIds )
#set( $trimmedUserId = $userId.trim() )
#if( $trimmedUserId.length() != 0 )
$util.qr( $nonEmptyUserIds.add($trimmedUserId) )
#end
#end
Since it's a check against your database, you need a datasource for your resolver, and a db query for the request mapping. If your db is a RDS, then you can use a SELECT. If it's a DyanmoDb, then BatchGetItem is the right choice.
In the response mapping, you should have db results to validate submitted user ids.

Symfony2 form validation of Doctrine2 object: accessing previous values on updates

I've written a class validator as a service and passed the doctrine entity manager to this validator. At this point everything works fine.
But now I need the unchanged object of $entry which is been updated in the form - or at least the previous values. I've tried some approaches, but did not succeed:
public function isValid($entry, Constraint $constraint)
{
$oldEntry = $this->em->getRepository('SomeBundle:Entry')->findOneBy(array('id' => $entry->getId()));
Doctrine fetches the same (changed) object as expected. But trying to refresh the object will reset both versions of the object:
$newEntry = clone $entry;
$this->em->detach($newEntry);
$this->em->refresh($entry);
$hoursOfOldEntry = $entry->calculateHours();
$this->em->merge($newEntry);
Another option could be to save the values of the object as array, refresh the object and reassign the saved values again after working on the original values. But this does not seem to be the best way, especially if the are many relations. I don't wont to touch the object within a validator, I just need the previous values!
Another approach could be using Doctrine\ORM\UnitOfWork#recomputeSingleEntityChangeSet(Doctrine\ORM\ClassMetadata $meta, $entity). But I don't think it's a good idea to use internal doctrine methods in a validator!
So how do I get the original object or the change set in a class validator?
This won't get you the original entity, but should get you a key/value array of the original fields:
$uow = $em->getUnitOfWork();
$originalData = $uow->getOriginalEntityData($entry);
http://www.doctrine-project.org/api/orm/2.0/source-class-Doctrine.ORM.UnitOfWork.html#2210

Symfony: Model Translation + Nested Set

I'm using Symfony 1.2 with Doctrine. I have a Place model with translations in two languages. This Place model has also a nested set behaviour.
I'm having problems now creating a new place that belongs to another node. I've tried two options but both of them fail:
1 option
$this->mergeForm(new PlaceTranslationForm($this->object->Translation[$lang->getCurrentCulture()]));
If I merge the form, what happens is that the value of the place_id field id an array. I suppose is because it is waiting a real object with an id. If I try to set place_id='' there is another error.
2 option
$this->mergeI18n(array($lang->getCurrentCulture()));
public function mergeI18n($cultures, $decorator = null)
{
if (!$this->isI18n())
{
throw new sfException(sprintf('The model "%s" is not internationalized.', $this->getModelName()));
}
$class = $this->getI18nFormClass();
foreach ($cultures as $culture)
{
$i18nObject = $this->object->Translation[$culture];
$i18n = new $class($i18nObject);
unset($i18n['id']);
$i18n->widgetSchema['lang'] = new sfWidgetFormInputHidden();
$this->mergeForm($i18n); // pass $culture too
}
}
Now the error is:
Couldn't hydrate. Found non-unique key mapping named 'lang'.
Looking at the sql, the id is not defined; so it can't be a duplicate record (I have a unique key (id, lang))
Any idea of what can be happening?
thanks!
It looks like the issues you are having are related to embedding forms within each other, which can be tricky. You will likely need to do things in the updateObject/bind methods of the parent form to get it to pass its values correctly to its child forms.
This article is worth a read:
http://www.blogs.uni-osnabrueck.de/rotapken/2009/03/13/symfony-merge-embedded-form/comment-page-1/
It gives some good info on how embedding (and mergeing) forms work. The technique the article uses will probably work for you, but I've not used I18n in sf before, so it may well be that there is a more elegant solution built in?

How can I use a stored procedure in a MySql database with Zend Framework?

I'm recently have learned to use Zend Framework. I did a simple CRUD application. But now I want to use a existing database for a more complex application and I want to know how I call a stored procedure in the Model, how to send parameters, how to read the results and store them in an array in PHP. Please. I appreciate any kind of help :)
It's not too hard. Here's an example of a MySQL stored procedure with an IN parameter, an OUT parameter, and a result set:
CREATE PROCEDURE MyProc(IN i INTEGER, OUT o INTEGER)
BEGIN
SELECT i+10 INTO o;
SELECT i, o;
END
You can call this with the query() method, and pass a parameter:
$stmt = $db->query("CALL MyProc(?, #output)", array(25));
print_r( $stmt->fetchAll() );
The trick is that MySQL stored procs might return multiple result sets (if the proc had multiple SELECT queries for instance). So the API must advance through all result sets before you can execute another SQL query. Or else you get the "Commands out of sync" error.
If you use the PDO_MySQL adapter:
while ($stmt->nextRowset()) { }
If you use the MySQLi adapter, you'll find that Zend_Db_Statement_Mysqli doesn't implement nextRowset(), so you have to call the internal mysqli connection object:
while ($db->getConnection()->next_result()) { }
Once you clear the result sets, you can run subsequent SQL queries, for example to fetch the value of the procedure's OUT parameter:
$stmt = $db->query("SELECT #output");
print_r( $stmt->fetchAll() );
Great answer from Bill. Just for completeness, if you encounter:
SQLSTATE[HY000]: General error: 2053
When using this method to get a result set from your procedure, check your arguments. I refactored a method and was passing NULLs as arguments to the procedure as the variables I'd used were out of scope. Once I'd fixed this silly mistake the problem went away (to be replaced by another):
SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other
unbuffered queries are active. Consider using PDOStatement::fetchAll().
I'm using $stmt->fetchAll() though. I switched to using prepare() and execute() in place of query(). Switching to mysqli from pdo_mysql in my Zend_Db config finally got things working for me. I found this information from the following SO question:
Call Multiple Stored Procedures with the Zend Framework
If someone is looking for ZendFramework 2 \ Zend Expressive using Zend\Db :
There is another way to do this using createStatement() method.
// prepare create statement from adapter
$stmt = $this->getAdapter()->createStatement();
$stmt->prepare('CALL myproc("myVal")');
// execute sql query
$records = $stmt->execute();
// manipulate results
if ($records instanceof ResultInterface && $records->isQueryResult()) {
$resultSet = new ResultSet;
$resultSet->initialize($records);
// return records if found
if (count($resultSet)) {
// return array of result set
return $resultSet->toArray();
}
// if no records found
return array()
}
$db = Zend_Db_Table::getDefaultAdapter();
$stmt = $db->query("CALL procedure()");
$data = $stmt->fetchAll();