How can I get all the modified fields before saving the editing in cake php? - entity

Using the
$entity->errors(); //is returning all errors.
to find changes before upgrading
There is something like
$entity = $this->Controller->patchEntity($entity , $this->request->data);
echo $entity->diff (); // how?

I guess you are looking for:
$entity->dirty()
If you want an array containing alla the dirty properties you can do
$entity->name = 'Foo';
$entity->description = 'Bar';
debug($entity->extract($entity->visibleProperties(), true));
you'll get
[
'name' => 'Foo',
'abbreviation' => 'Bar'
]
see the manual

Related

backdrop cms module-created blocks deltas not working

(tagging with drupal7 because i cannot create a tag for backdrop)
i have a fresh backdrop install, with a new theme duped from bartik, and a new layout duped from moscone_flipped. no code changes to those yet.
i have a module that creates 2 simple blocks, mostly just some html. i have implemented hook_block_info() and hook_block_view(). i can place blocks into regions in the layout using the admin ui. i can see each block on the front end page when i place either one of them. but not both. when i have both blocks placed in the layout, for some reason both regions display the output from the same block. and i have verified that it is always the first block defined in the array returned from hook_block_info(). i have cleared caches, checked code, etc.
has anyone seen this before?
btw, i just applied the recent security upgrade, and the behavior is the same both before and after the upgrade.
i will paste in the module code below, in case i have missed something.
thanks for any help anyone can provide.
// implements hook_block_info()
function mbr_block_info()
{
$info = array();
$info['rate-tables'] = array(
'info' => 'Rate Tables (Buttons)',
'description' => 'The displays the rate table links for the sidebar',
);
$info['mbr-footer'] = array(
'info' => 'MBR Footer',
'description' => 'Displays footer links, disclaimer, copyright',
);
return($info);
}
// implements hook_block_view()
function mbr_block_view($delta = '', $settings = array(), $contexts = array())
{
$block = array();
switch($delta)
{
case 'mbr-footer':
$subject = null;
$mbrFooter = getMBRFooterBlock();
$block = array('subject' => $subject, 'content' => $mbrFooter);
case 'rate-tables':
$subject = null;
$rateTables = getRateTablesBlock();
$block = array('subject' => $subject, 'content' => $rateTables);
}
return($block);
}

A new entity was found through the relationship. Doctrine

The application has thrown an exception!
Doctrine\ORM\ORMInvalidArgumentException
A new entity was found through the relationship 'Core\Model\Filter#category' that was not configured to cascade persist operations for entity: Core\Model\Category#00000000314fc99200005639c0395a5e. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist this association in the mapping for example #ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'Core\Model\Category#__toString()' to get a clue.
This function cause an exception.
Some comits in code.
It is ZendFramework 2.
protected function handleCategory( $data, \Core\Model\Project $project )
{
$filter = $this->sl()->get( "Core\Filter\JSON\Category" );
$filter->setData( $data );
if( !$filter->isValid() ){
$id = #$data[ 'id' ];
$report = array(
'id' => $id,
'messages' => $filter->getMessages()
);
return $report;
}
$filteredData = $filter->getValues();
$repo = $this->em()->getRepository( "Core\Model\Category" );
$category = $repo->findOneBy(
array(
'id' => $filteredData[ 'id' ],
'project' => $project->getId()
)
);
$b = false;
if( !$category ){
$b = true;
$category = new \Core\Model\Category;
$category->setProject( $project )
->setCreatedAt( new \DateTime() );
}
$category->setUpdatedAt( new \DateTime() );
/* Hydrate Category */
$hydrator = $this->sl()->get( "Core\Hydrator\JSON\Category" );
$hydrator->hydrate( $filteredData, $category );
/* Persist Category */
$this->em()->persist($category);
if($b)
{
/* Return Filter Data */
$filterData = $hydrator->get();
/* Hydrate Filter */
$filterHydrator = $this->sl()->get( 'Core\Hydrator\JSON\Filter' );
//$filtersObj = array();
foreach($filterData as $i => $fdata)
{
$filterObj = new \Core\Model\Filter;
$filterObj->setProject($project)->setCategory($category);
$filterHydrator->hydrate($fdata, $filterObj);
$this->em()->persist($filterObj);
/*Breaks after any flush after second persist*/
$this->em()->flush();
}
}
return true;
}
I tried to solve this problem by:
MERGE, but get another exception, A managed dirty+entity [...]
cascade={"persist"}, but nothing happend.
rewrite code in that what you see, i made all persists in one function one by one with one EntityManager.(If i missing something please tell me)
Never work before with ZendFramework. I love Symfony with app/console manager, all entities with tables creates authomatically.
Solved this problem with adding
$this->em()->clear('Filter');
after
$this->em()->persist($filterObj);
And we can remove
$this->em()->flush();
To do script faster. I paste it in the end.
I think this is not good idea, but it works.
I still waiting for your answers.

cakephp see the compiled SQL Query before execution

My query gets the timeout error on each run. Its a pagination with joins.
I want to debug the SQL, but since I get a timeout, I can't see it.
How can I see the compiled SQL Query before execution?
Some cake code:
$this -> paginate = array(
'limit' => '16',
'joins' => array( array(
'table' => 'products',
'alias' => 'Product',
'type' => 'LEFT',
'conditions' => array('ProductModel.id = Product.product_model_id')
)),
'fields' => array(
'COUNT(Product.product_model_id) as Counter',
'ProductModel.name'
),
'conditions' => array(
'ProductModel.category_id' => $category_id,
),
'group' => array('ProductModel.id')
);
First off, set the debug variable to 2 in app/config/config.php.
Then add:
<?php echo $this->element('sql_dump');?>
at the end of your layout. This should actually be commented out in your default cake layout.
You will now be able see all SQL queries that go to the database.
Now copy the query and use the SQL EXPLAIN command (link is for MySQL) over the database to see what the query does in the DBMS. For more on CakePHP debugging check here.
Since your script doesn't even render you can try to get the latest log directly from the datasource with:
function getLastQuery()
{
$dbo = $this->getDatasource();
$logs = $dbo->getLog();
$lastLog = end($logs['log']);
return $lastLog['query'];
}
This needs to be in a model since the getDatasource() function is defined in a model.
Inspect the whole $logs variable and see what's in there.
One more thing you can do is ....
Go to Cake/Model/DataSource/DboSource.php and locate function execute() and print $sql variable.
That should print the sql.
This certainly is not be the cleanest way (as you are changing Cake directory) .. but certainly would be quickest just to debug if something is not working with sql.
Try...
function getLastQuery($model) {
$dbo = $model->getDatasource();
$logData = $dbo->getLog();
$getLog = end($logData['log']);
echo $getLog['query'];
}
Simple way to show all executed query of your given model:
$sqllog = $this->ModelName->getDataSource()->getLog(false, false);
debug($sqllog);
class YourController extends AppController {
function testfunc(){
$this->Model->find('all', $options);
echo 'SQL: '.$this->getLastQuery();
}
function getLastQuery()
{
$dbo = ConnectionManager::getDataSource('default');
$logs = $dbo->getLog();
$lastLog = end($logs['log']);
return $lastLog['query'];
}
}
or you can get all the query by adding following line in to the function execute() in lib/Cake/Model/DataSource.php
Debugger::dump($sql);
set the debug variable to 2 in app/config/config.php.
echo $this->Payment->save();
Out put like =>SQL Query: INSERT INTO photoora_photoorange.payments VALUES (*******)
[insert query][2]
set the debug variable to 2 in app/config/config.php.
And

limit number of results using magento API V2

Hi I have searched the site for my question but haven't found an easy solution and I think the issue is so basic.
I'm using Api V2 so maybe there's a solution now. Here I go, this is my code:
$api_soap_url = 'http://localhost/magento/api/v2_soap?wsdl=1';
$client = new SoapClient($api_soap_url);
$session_id = $client->__soapCall('login',array($user, $pw));
$data = array($session_id);
$result = $client->__soapCall('customerCustomerList', $data);
This returns all results, I need to limit number of result so I have tried using filters and other solutions found here but no luck.
The only one I haven't tried is this one:
Control the number of results from a Magento API call
But filtering by date doesn't solve my problem and rewriting classes is a ver complex solution for such a simple need.
Thanks in advance
I'm not sure the filter can limit number of result but you can try this:
$complexFilter = array(
'complex_filter' => array(
array(
'key' => 'created_at',
'value' => array('key' => 'gt', 'value' => '2012-05-13 06:11:00')
// where created_at is greater than 2012-05-13 06:11:00
// For example: eq (equals), neq (not equals), gt (greater than), lt (less than), etc.
)
)
);
$result = $client->customerCustomerList($session, $complexFilter);
I ended up overriding app/code/core/Mage/Sales/Model/Order/Api.php, adding a "special magic" field called "collection.limit". Your mileage may vary; I have tight controls on both the Magento installation and the programs (in this case, a set of C# programs) accessing the Magento installation.
My caller simply uses the "magic field" as a key/ value pair, something like this (please test, again, I was calling from C#, so this php should be considered suspect):
$collectionLimitClause = array (
'key' => 'collection.limit',
'value' => array('key' => 'eq', 'value' => '10')
);
In my Magento installation (this part is tested, live and running), I created a Sales/Model/Order/Api.php in my local namespace and over-rode the items function. Around the 32nd or so line of that function, you'll see this:
$apiHelper = Mage::helper('api');
$filters = $apiHelper->parseFilters($filters, $this->_attributesMap['order']);
try {
foreach ($filters as $field => $value) {
$orderCollection->addFieldToFilter($field, $value);
}
} catch (Mage_Core_Exception $e) {
$this->_fault('filters_invalid', $e->getMessage());
}
Instead, I "catch" my own magic limiter with the strncmp here, with an if-else inside the foreach:
$apiHelper = Mage::helper('api');
$filters = $apiHelper->parseFilters($filters, $this->_attributesMap['order']);
try {
foreach ($filters as $field => $value) {
if( !strncmp($field,"collection.limit",16) ) {
$orderCollection->getSelect()->limit($value['eq']);
}
else {
$orderCollection->addFieldToFilter($field, $value);
}
}
} catch (Mage_Core_Exception $e) {
$this->_fault('filters_invalid', $e->getMessage());
}
I'm not overly excited by this, but, I think it's pretty safe and it works.

Symfony file upload - "Array" stored in database instead of the actual filename

I'm using Symfony 1.4.4 and Doctrine and I need to upload an image on the server.
I've done that hundreds of times without any problem but this time something weird happens : instead of the filename being stored in the database, I find the string "Array".
Here's what I'm doing:
In my Form:
$this->useFields(array('filename'));
$this->embedI18n(sfConfig::get('app_cultures'));
$this->widgetSchema['filename'] = new sfWidgetFormInputFileEditable(array(
'file_src' => '/uploads/flash/'.$this->getObject()->getFilename(),
'is_image' => true,
'edit_mode' => !$this->isNew(),
'template' => '<div id="">%file%</div><div id=""><h3 class="">change picture</h3>%input%</div>',
));
$this->setValidator['filename'] = new sfValidatorFile(array(
'mime_types' => 'web_images',
'path' => sfConfig::get('sf_upload_dir').'/flash',
));
In my action:
public function executeIndex( sfWebRequest $request )
{
$this->flashContents = $this->page->getFlashContents();
$flash = new FlashContent();
$this->flashForm = new FlashContentForm($flash);
$this->processFlashContentForm($request, $this->flashForm);
}
protected function processFlashContentForm($request, $form)
{
if ( $form->isSubmitted( $request ) ) {
$form->bind( $request->getParameter( $form->getName() ), $request->getFiles( $form->getName() ) );
if ( $form->isValid() ) {
$form->save();
$this->getUser()->setFlash( 'notice', $form->isNew() ? 'Added.' : 'Updated.' );
$this->redirect( '#home' );
}
}
}
Before binding my parameters, everything's fine, $request->getFiles($form->getName()) returns my files.
But afterwards, $form->getValue('filename') returns the string "Array".
Did it happen to any of you guys or do you see anything wrong with my code?
Edit: I added the fact that I'm embedding another form, which may be the problem (see Form code above).
Alright, I got it. I wasn't properly declaring my validator.
What i should've done is:
$this->setValidator('filename', new sfValidatorFile(array(
'mime_types' => 'web_images',
'path' => sfConfig::get('sf_upload_dir').'/flash',
)));
Silly mistake, I hope that will help those who have the same problem.
Alternatively you can use;
$this->validatorSchema['filename']
in place of;
$this->setValidator['filename']