Symfony3 Datatable unable to render - php

In a MySQL database, I'm storing a VARBINARY(16) for an IPv4/IPv6 address. In order to display this on a form, I have created a DataTransformer in order to use the built-in inet_pton and inet_ntop functions.
I would like to display this in a Datatable, so searching by IP address would be possible. Unfortunately, by using my typical datatable setup, I get 500 server errors.
Through using browser developer tools, I'm able to determine that the results from the AJAX call is getting partial data, the actual IP address is listed as a resource, not the real data.
The error says: An unexpected value could not be normalized: NULL
In the stack trace, I see:
at Serializer ->normalize (resource, 'json', array())
in vendor/symfony/symfony/src/Symfony/Component/Serializer/Serializer.php at line 152
at Serializer ->normalize (array('id' => '5', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true))), 'json', array())
in vendor/symfony/symfony/src/Symfony/Component/Serializer/Serializer.php at line 152
at Serializer ->normalize (array(array('id' => '5', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true))), array('id' => '6', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true)))), 'json', array())
in vendor/symfony/symfony/src/Symfony/Component/Serializer/Serializer.php at line 152
at Serializer ->normalize (array('draw' => '1', 'recordsTotal' => '2', 'recordsFiltered' => '2', 'data' => array(array('id' => '5', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true))), array('id' => '6', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true))))), 'json', array())
in vendor/symfony/symfony/src/Symfony/Component/Serializer/Serializer.php at line 115
at Serializer ->serialize (array('draw' => '1', 'recordsTotal' => '2', 'recordsFiltered' => '2', 'data' => array(array('id' => '5', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true))), array('id' => '6', 'ipAddress' => resource, 'sg_datatables_editable' => array(false), 'sg_datatables_actions' => array(array('network_ipaddress_show' => true))))), 'json')
in vendor/sg/datatablesbundle/Sg/DatatablesBundle/Datatable/Data/DatatableQuery.php at line 743
Seeing the JSON calls, I implemented the JsonSerializable interface, but it seems that it's not being pulled that way.
While an option would be to place the inet_pton or inet_ntop in the entity directly, I believe I would lose validation.
What interface can I implement to allow Datatables to pull my IPAddress entity, and display the IP address properly?
Note that the data isn't translated from the entity (VARBINARY) to a readable string that the datatable requires. The stack trace shows that it's a "resource".
Added Code:
My Entity:
<?php
namespace AppBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use JsonSerializable;
/**
* #ORM\Table(name="ip_address")
*/
class IPAddress implements JsonSerializable
{
/**
* #var int
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var mixed
* #ORM\Column(name="ip_address", type="binary", length=16, nullable=false, unique=true)
*/
private $ipAddress;
/**
* Set IP Address
* #param mixed $ipAddress
* #return IPAddress
*/
public function setIpAddress($ipAddress)
{
$this->ipAddress = $ipAddress;
return $this;
}
/**
* Get IP Address
* #return mixed
*/
public function getIpAddress()
{
return $this->ipAddress;
}
public function jsonSerialize()
{
return array(
'ipAddress' => inet_pton($this->ipAddress),
);
}
The Datatable class:
<?php
namespace AppBundle\Datatables;
use Sg\DatatablesBundle\Datatable\View\AbstractDatatableView;
use Sg\DatatablesBundle\Datatable\View\Style;
/**
* Class IPAddressDatatable
* #package AppBundle\Datatables
*/
class IPAddressDatatable extends AbstractDatatableView
{
/**
* {#inheritdoc}
*/
public function buildDatatable(array $options = array())
{
$this->features->set(array(
'auto_width' => true,
'defer_render' => false,
... other default features not listed ...
'delay' => 0,
'extensions' => array()
));
$this->ajax->set(array(
'url' => $this->router->generate('network_ipaddress_results'),
'type' => 'GET'
));
$this->options->set(array(
'display_start' => 0,
'defer_loading' => -1,
... other default options not listed ...
'use_integration_options' => false,
'force_dom' => false
));
$this->columnBuilder
->add('ipAddress', 'column', array(
'title' => 'IP Address',
'width' => '85%',
))
->add(null, 'action', array(
'title' => '',
'width' => '15%',
'actions' => array(
array(
'route' => 'network_ipaddress_show',
'route_parameters' => array(
'plan_id' => 'id'
),
'label' => $this->translator->trans('datatables.actions.show'),
'icon' => 'fi-eye icon-size-14',
'attributes' => array(
'rel' => 'tooltip',
'title' => $this->translator->trans('datatables.actions.show'),
'class' => 'tiny button',
'role' => 'button'
),
),
),
));
;
}
... getEntity and getName not shown for brevity ...
}
The Controller (at least the relevant parts):
/**
* Lists all IP Addresses.
*
* #Route("/", name="network_ipaddress_index")
* #Method("GET")
* #return IPAddressController
*/
public function indexAction()
{
$datatable = $this->get('app.datatable.ipaddress');
$datatable->buildDatatable();
return $this->render(':network:ipaddress_datatable.html.twig', array(
'datatable' => $datatable,
));
}
/**
* Returns a response, only used for datatables
*
* #Route("/results", name="network_ipaddress_results")
* #Method("GET")
* #return IPAddressController
*/
public function indexResultsAction()
{
$datatable = $this->get('app.datatable.ipaddress');
$datatable->buildDatatable();
// I believe that the entity data would have to be translated here into printable a format
$query = $this->get('sg_datatables.query')->getQueryFrom($datatable);
return $query->getResponse();
}

As it turns out, there is a closure available pre-rendering in the stwe/DatatablesBundle.
So, the function that is required in the above Datatables class:
/**
* {#inheritdoc}
*/
public function getLineFormatter()
{
$formatter = function($line){
$str = stream_get_contents($line['ipAddress']);
if( strlen( $str ) == 16 OR strlen( $str ) == 4 ){
$line['ipAddress'] = inet_ntop( pack( "A".strlen( $str ) , $str ) );
}
return $line;
};
return $formatter;
}

Related

Cannot get value from $form_state in custom Drupal 8 Webform Handler

I am working in Drupal 8 and am building a custom WebformHandler. I have an element with an ajax component. I cannot seem to access any form values via $form_state->getValue('key') within the ajax callback (nor anywhere for that matter). I have been bashing my head against the wall for a while.
I've followed every guide that I can find on the internet, but to no success. My code is provided below.
<?php
namespace Drupal\campaign_monitor_transactional\Plugin\WebformHandler;
use Drupal\Core\Form\FormStateInterface;
use Drupal\samlauth\Element\MultiValue;
use Drupal\webform\Plugin\WebformHandlerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Test Campaign Monitor webform handler
*
* #WebformHandler(
* id = "campaign_monitor_transactional",
* label = #Translation("Campaign Montior Transactional"),
* category = #Translation("Campaign Monitor"),
* description = #Translation("Trigger Campaign Monitor Transaction Emails"),
* cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_UNLIMITED,
* results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_PROCESSED,
*
* )
*/
class TransactionalWebformHandler extends WebformHandlerBase {
/**
* Logger service
*
* #var \Drupal\Core\Logger\LoggerChannelFactory
*/
protected $loggerFactory;
/**
* The Campaign Monitor RESTCLient
*
* #var \Drupal\CampaignMonitorRestClientFactory
*/
protected $campaignMonitorRESTClient;
/**
* {#inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition)
{
$instance = parent::create(
$container,
$configuration,
$plugin_id,
$plugin_definition
);
// TODO webform_campaign_monitor may not be correct
$instance->loggerFactory = $container
->get('logger.factory')
->get('webform_campaign_monitor');
$instance->campaignMonitorRESTClient = $container
->get('campaign_monitor_rest_client');
return $instance;
}
/**
* {#inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state)
{
// Campaign monitor settings
$form['template_settings'] = [
'#type' => 'details',
'#title' => $this->t('Template settings'),
'#open' => TRUE
];
# I am just using this for testing purposes
$form['example_select'] = [
'#type' => 'select',
'#title' => $this->t('Select element'),
'#options' => [
'1' => $this->t('One'),
'2' => $this->t('Two'),
'3' => $this->t('Three'),
]
];
$form['template_settings']['email_template'] = [
'#type' => 'select',
'#title' => $this->t('Email Template'),
'#options' => $this->getTransactionEmailOptions(),
'#ajax' => [
'callback' => [$this, 'fetchParamsCallback'],
'wrapper' => 'cm-param-textarea',
'progress' => [
'type' => 'throbber',
'message' => $this->t('Loading params...')
]
]
];
$form['template_settings']['params'] = [
'#type' => 'textarea',
'#title' => $this->t('Campaign Monitor Params'),
'#disabled' => True,
'#prefix' => '<div id="cm-param-textarea">',
'#suffix' => '</div>'
];
return $form;
}
/**
* {#inheritdoc}
*/
public function submitConfigurationForm(array &$form, FormStateInterface $form_state)
{
parent::submitConfigurationForm($form, $form_state);
$this->applyFormStateToConfiguration($form_state);
}
/**
* Loads Campaign Monitor params based on selected email template
*/
public function fetchParamsCallback(array &$form, FormStateInterface $form_state)
{
$smart_email_id = $form_state->getValue('example_select');
### ISSUE IS HERE.... $SMART_EMAIL_ID is blank
return [
'#type' => 'textfield',
'#size' => '60',
'#disabled' => TRUE,
'#value' => 'SEI: ' . $smart_email_id,
'#prefix' => '<div id="edit-output">',
'#suffix' => '</div>',
];
}
/**
* Helper function producing sender dropdown options
* #return array
* Options for sender dropdown
*/
protected function getSenderOptions()
{
return array(
'you' => 'Your Email',
'custom' => 'Custom email address(es)',
'author' => 'Webform author',
'none' => 'None'
);
}
/**
* Helper function to fetch all active transactional emails
*
* #return array
* Options for transactional email dropdown
*/
protected function getTransactionEmailOptions()
{
$options = array();
# TODO client ID should not be hard coded
$clientID = 'XXX';
$params = [
'query' => [
'status' => 'all',
'clientID' => $clientID
]
];
$email_templates = $this->campaignMonitorRESTClient
->get('transactional/smartEmail', $params)
->getBody()
->getContents();
foreach(json_decode($email_templates) as $template) {
$options[$template->ID] = $template->Name;
}
return $options;
}
}

Cakephp migrations: Rename fields and update values in database

I'm trying to rename fields and update values on already inserted rows in cakephp migrations.
Workflow:
In before method i fetch all already added rows in my db so i will be able to update them in after method.
Then migration happens, which create columns value_from and value_to and also drops columns price_from and price_to
Then i try in my after method fetch all "new" rows, where i wan't to update values from old ones, but error happens, because find('all') method throws errors
My code:
class ShippingTypeCostCalculationM1483610977ProjectPluginLogistics extends CakeMigration {
/**
* Data which will be inserted in modified table shipping costs
* #var
*/
private $data;
/**
* Migration description
*
* #var string
* #access public
*/
public $description = '';
/**
* Actions to be performed
*
* #var array $migration
* #access public
*/
public $migration = array(
'up' => array(
'create_field' => array(
'shipping_costs' => array(
'shipping_type' => array('type' => 'string', 'null' => false, 'default' => 'order_sum', 'length' => 20, 'collate' => 'utf8_unicode_ci', 'charset' => 'utf8', 'after' => 'customer_type'),
'value_from' => array('type' => 'decimal', 'null' => false, 'default' => NULL, 'length' => '10,4', 'after' => 'shipping_type'),
'value_to' => array('type' => 'decimal', 'null' => false, 'default' => NULL, 'length' => '10,4', 'after' => 'value_from'),
),
),
'drop_field' => array(
'shipping_costs' => array('price_from', 'price_to',),
)
),
'down' => array(
'drop_field' => array(
'shipping_costs' => array('shipping_type', 'value_from', 'value_to',),
),
),
'create_field' => array(
'shipping_costs' => array(
'price_from' => array('type' => 'decimal', 'null' => false, 'default' => NULL, 'length' => '10,4'),
'price_to' => array('type' => 'decimal', 'null' => false, 'default' => NULL, 'length' => '10,4'),
),
)
);
/**
* Before migration callback
*
* #param string $direction, up or down direction of migration process
* #return boolean Should process continue
* #access public
*/
public function before($direction) {
$shippingCost = ClassRegistry::init('Logistics.ShippingCost');
$this->data = $shippingCost->find('all');
return true;
}
/**
* After migration callback
*
* #param string $direction, up or down direction of migration process
* #return boolean Should process continue
* #access public
*/
public function after($direction) {
$shippingCost = ClassRegistry::init('Logistics.ShippingCost');
// This is where error happens
$shippingCosts = $shippingCost->find('all');
foreach ($this->data as $item) {
$shippingCost = $shippingCosts->get($item['shipping_costs']['id']);
$shippingCost->value_from = $item['shipping_costs']['price_from'];
$shippingCost->value_to = $item['shipping_costs']['price_to'];
$shippingCosts->save($shippingCost);
}
return true;
}
}
PROBLEM:
In after method, cake php is still trying to fetch values like price_from or price_to which are already deleted.
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'ShippingCost.price_from' in 'field list'
How can i overcome my problem?
If you need any additional informations, please let me know and i will provide. Thank you in advance!
You run the callbacks in any case, the code is always executed.
public function after($direction) {...}
See the argument? This can be up and down. You need to wrap your code that you want to run before or after applying the migration accordingly in a check like if ($direction === 'down') { ... }.
Also I don't think your approach is well done. If you have a lot of data you can run out of memory.
Create a migration that will add the new fields. Then another migration file that will just do the data transformation and process the data in chunks. And a third one that will delete the no longer needed fields after that. The simple reason is: Separate data from schema changes.

Drupal Field API - Settings List

I'm trying to create a 'link_field' in Drupal through a module, I've got the following code but I'd like to configure the field settings to do the following:
Not require title
Update the number of values to unlimited
I'm struggling to find any information around what setting key/pair values you can pass through for these, anyone able to offer some guidance on these?
<?php
/**
* Implements hook_enable().
*
* Create a field. Fields can be created without any needs to attach them to
* entities.
*/
function youtube_carousel_enable() {
$field = array(
'field_name' => 'ytcarousel_field',
'type' => 'link_field',
);
field_create_field($field);
/**
* Bind field to a entity bundle.
*/
$instance = array(
'field_name' => $field['field_name'],
'entity_type' => 'node',
'bundle' => 'homepage',
'label' => 'YouTube Video'
);
field_create_instance($instance);
}
/**
* Implements hook_disable().
*
* Remove field from node bundle (content type) and then delete the field.
*/
function youtube_carousel_disable() {
$instance = array(
'field_name' => 'ytcarousel_field',
'entity_type' => 'node',
'bundle' => 'homepage',
'label' => 'YouTube Video'
);
field_delete_instance($instance);
field_delete_field($instance['field_name']);
print 'Removed ' . $instance['field_name'] . "\n";
}
?>
Cheers
After viewing the HTML source to get key/value pairs I've managed to do something similar to the above with the following code:
<?php
/**
* Implements hook_enable().
*
* Create a field. Fields can be created without any needs to attach them to
* entities.
*/
function youtube_carousel_enable() {
$field = array(
'field_name' => 'ytcarousel_field',
'type' => 'link_field',
'cardinality' => -1
);
field_create_field($field);
/**
* Bind field to a entity bundle.
*/
$instance = array(
'field_name' => $field['field_name'],
'entity_type' => 'node',
'bundle' => 'homepage',
'label' => 'YouTube Video',
'settings' => array('title' => 'required')
);
field_create_instance($instance);
}
/**
* Implements hook_disable().
*
* Remove field from node bundle (content type) and then delete the field.
*/
function youtube_carousel_disable() {
$instance = array(
'field_name' => 'ytcarousel_field',
'entity_type' => 'node',
'bundle' => 'homepage',
'label' => 'YouTube Video',
'settings' => array('title' => 'required')
);
field_delete_instance($instance);
field_delete_field($instance['field_name']);
print 'Removed ' . $instance['field_name'] . "\n";
}
?>
The cardinality controls have many instances the value can have, "-1" is unlimited.
'cardinality' => -1
The title attribute is controlled via the instance not the field itself, I believe, and it uses text based values rather than numeric.
'settings' => array('title' => 'required')

symfony2 doctrine ResultSetMapping error

Here I am try to use ResultSetMapping to map the result which generate by nativeQuery. But I have no idea about why the doctrine always throw Undefined index error. anyone can help me out from this problem?
Here is my code:
the PlaceMarkerRepository:
namespace Leo\FoodRadarBundle\Entity;
use Doctrine\ORM\EntityRepository;
use Doctrine\ORM\Query\ResultSetMappingBuilder;
/**
* PlaceMarkerRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class PlaceMarkerRepository extends EntityRepository
{
public function findNearBy($query,$lat, $lng, $radius){
$rsm = new ResultSetMappingBuilder($this->getEntityManager());
// $rsm = new ResultSetMappingBuilder();
// $rsm->addRootEntityFromClassMetadata('LeoFoodRadarBundle:PlaceMarker', 'p');
// $rsm->addJoinedEntityFromClassMetadata('LeoFoodRadarBundle:Coordinate', 'c', 'p', 'coordinate', array('id' => 'coordinate_id'));
$rsm->addEntityResult('LeoFoodRadarBundle:PlaceMarker', 'p');
$rsm->addFieldResult('p', 'id', 'id');
$rsm->addFieldResult('p', 'name', 'name');
$rsm->addJoinedEntityResult('LeoFoodRadarBundle:Coordinate' , 'c', 'p', 'coordinate');
$rsm->addFieldResult('c', 'coordinate_id', 'id');
$rsm->addFieldResult('c', 'latitude', 'latitude');
$rsm->addFieldResult('c', 'longitude', 'longitude');
$sql ="SELECT p.id, p.name, c.latitude, c.longitude, c.id as coordinate_id
FROM placeMarker p join coordinate c on p.coordinate_id = c.id
";
$this->getEntityManager()->createNativeQuery($sql, $rsm)->getResult();
}
}
and PlaceMark:
namespace Leo\FoodRadarBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Leo\FoodRadarBundle\Entity\PlaceMarker
*
* #ORM\Table(name="placeMarker")
* #ORM\Entity(repositoryClass="Leo\FoodRadarBundle\Entity\PlaceMarkerRepository")
*/
class PlaceMarker {
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #var Coordinate coordinate
* #ORM\OneToOne(targetEntity="Coordinate")
* #ORM\JoinColumn(name="coordinate_id", referencedColumnName="id")
*/
private $coordinate;
/**
*
* #var Address address
* #ORM\OneToOne(targetEntity="Address")
* #ORM\JoinColumn(name="address_id", referencedColumnName="id")
*/
private $address;
/**
*
* #ORM\Column(name="name", type="string", length=100)
*/
private $name;
/**
* Get id
*
* #return integer
*/
public function getId() {
return $this->id;
}
/**
* Set coordinate
*
* #param Leo\FoodRadarBundle\Entity\Coordinate $coordinate
* #return PlaceMarker
*/
public function setCoordinate(\Leo\FoodRadarBundle\Entity\Coordinate $coordinate = null) {
$this->coordinate = $coordinate;
return $this;
}
/**
* Get coordinate
*
* #return Leo\FoodRadarBundle\Entity\Coordinate
*/
public function getCoordinate() {
return $this->coordinate;
}
/**
* Set address
*
* #param Leo\FoodRadarBundle\Entity\Address $address
* #return PlaceMarker
*/
public function setAddress(\Leo\FoodRadarBundle\Entity\Address $address = null) {
$this->address = $address;
return $this;
}
/**
* Get address
*
* #return Leo\FoodRadarBundle\Entity\Address
*/
public function getAddress() {
return $this->address;
}
/**
* Set name
*
* #param string $name
* #return PlaceMarker
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* #return string
*/
public function getName()
{
return $this->name;
}
}
The Coordinate:
<?php
namespace Leo\FoodRadarBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* Leo\FoodRadarBundle\Entity\Coordinate
*
* #ORM\Table(name="coordinate")
* #ORM\Entity
*/
class Coordinate
{
/**
* #var integer $id
*
* #ORM\Column(name="id", type="integer")
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* #ORM\Column(type="float")
*/
private $longitude;
/**
* #ORM\Column(type="float")
*/
private $latitude;
/**
* Get id
*
* #return integer
*/
public function getId()
{
return $this->id;
}
/**
* Get longitude
* #return float
*/
public function getLongitude() {
return $this->longitude;
}
/**
* Set longitude
*/
public function setLongitude($longitude) {
$this->longitude = $longitude;
}
/**
* Get Latitude
* #return float
*/
public function getLatitude() {
return $this->latitude;
}
/**
* Set Latitude
*/
public function setLatitude($latitude) {
$this->latitude = $latitude;
}
}
the error caused by this statement:
$targetClass = $this->_ce[$relation['targetEntity']];
the information about error is:
Notice: Undefined index: Leo\FoodRadarBundle\Entity\Coordinate in /Volumes/DATA/LEO/Sites/FoodRadar/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php line 427
ErrorHandler ->handle ('8', 'Undefined index: Leo\FoodRadarBundle\Entity\Coordinate', '/Volumes/DATA/LEO/Sites/FoodRadar/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php', '427', array('row' => array('id' => '1', 'name' => 'test', 'latitude' => '233.234342', 'longitude' => '-232.23232323232', 'coordinate_id' => '2'), 'cache' => array('id' => array('fieldName' => 'id', 'type' => object(IntegerType), 'isIdentifier' => true, 'dqlAlias' => 'p'), 'name' => array('fieldName' => 'name', 'type' => object(StringType), 'isIdentifier' => false, 'dqlAlias' => 'p'), 'latitude' => array('fieldName' => 'latitude', 'type' => object(FloatType), 'isIdentifier' => false, 'dqlAlias' => 'c'), 'longitude' => array('fieldName' => 'longitude', 'type' => object(FloatType), 'isIdentifier' => false, 'dqlAlias' => 'c'), 'coordinate_id' => array('fieldName' => 'id', 'type' => object(IntegerType), 'isIdentifier' => true, 'dqlAlias' => 'c')), 'result' => array(object(PlaceMarker)), 'id' => array('p' => '|1', 'c' => '|2'), 'nonemptyComponents' => array('p' => true, 'c' => true), 'rowData' => array('p' => array('id' => '1', 'name' => 'test'), 'c' => array('latitude' => '233.234342', 'longitude' => '-232.23232323232', 'id' => '2')), 'dqlAlias' => 'c', 'data' => array('latitude' => '233.234342', 'longitude' => '-232.23232323232', 'id' => '2'), 'entityName' => 'LeoFoodRadarBundle:Coordinate', 'parentAlias' => 'p', 'path' => 'p.c', 'parentObject' => object(PlaceMarker), 'parentClass' => object(ClassMetadata), 'oid' => '000000003e34db9d00000000492221b6', 'relationField' => 'coordinate', 'relation' => array('fieldName' => 'coordinate', 'targetEntity' => 'Leo\FoodRadarBundle\Entity\Coordinate', 'joinColumns' => array(array('name' => 'coordinate_id', 'unique' => true, 'nullable' => true, 'onDelete' => null, 'columnDefinition' => null, 'referencedColumnName' => 'id')), 'mappedBy' => null, 'inversedBy' => null, 'cascade' => array(), 'orphanRemoval' => false, 'fetch' => '2', 'type' => '1', 'isOwningSide' => true, 'sourceEntity' => 'Leo\FoodRadarBundle\Entity\PlaceMarker', 'isCascadeRemove' => false, 'isCascadePersist' => false, 'isCascadeRefresh' => false, 'isCascadeMerge' => false, 'isCascadeDetach' => false, 'sourceToTargetKeyColumns' => array(*DEEP NESTED ARRAY*), 'joinColumnFieldNames' => array(*DEEP NESTED ARRAY*), 'targetToSourceKeyColumns' => array(*DEEP NESTED ARRAY*)), 'reflField' => object(ReflectionProperty), 'reflFieldValue' => null, 'element' => object(Coordinate), 'entityKey' => '0', 'resultKey' => '0'))
in /Volumes/DATA/LEO/Sites/FoodRadar/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php at line 427 -+
Finally, I found the reason why caused this problem. I think this because resultsetmapping runs internally, So it can't understand the logic name which provide by Symfony. The solution for this problem is that changing logical name to full path name. then it will work.

more type on a column of an entity in doctrine

I am currently working on parsing my entity files in zf2
I have following code for parsing an entity :
$classname = get_class($this->object);
$cmf = $this->em->getMetadataFactory();
$class = $cmf->getMetadataFor($classname);
$fields = $class->fieldMappings;
it returns :
array
'id' =>
array
'fieldName' => string 'id' (length=2)
'type' => string 'integer' (length=7)
'length' => null
'precision' => int 0
'scale' => int 0
'nullable' => boolean false
'unique' => boolean false
'id' => boolean true
'columnName' => string 'id' (length=2)
'artist' =>
array
'fieldName' => string 'artist' (length=6)
'type' => string 'string' (length=6)
'length' => null
'precision' => int 0
'scale' => int 0
'nullable' => boolean false
'unique' => boolean false
'columnName' => string 'artist' (length=6)
'title' =>
array
'fieldName' => string 'title' (length=5)
'type' => string 'string' (length=6)
'length' => null
'precision' => int 0
'scale' => int 0
'nullable' => boolean false
'unique' => boolean false
'columnName' => string 'title' (length=5)
I want to add a new type to my collumns. For example for configuring a column is uploadfield or Datepicker :
/**
* #ORM\Column(type="string")
* #type = 'datepicker'
*/
protected $publishdate;
and get that datepicker in class meta datas (for creating input elements in zend form)
any suggestion ?
fixed by
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
$reflClass = new \ReflectionClass($classname);
foreach ($reflClass->getProperties() as $property) {
var_dump($reader->getPropertyAnnotations($property));
}
and this
namespace Admin\Model;
use Doctrine\ORM\Mapping as ORM,
Admin\Scripts AS Scripts,
Doctrine\ORM\Mapping\Annotation as Ano;
/**
* #Annotation
* #Target("PROPERTY")
*/
class sina extends \Doctrine\Common\Annotations\Annotation
{
/** #var string */
public $sina;
}
/**
* A news entity.
*
* #ORM\Entity
* #ORM\Table(name="news")
* #property string $artist
* #property string $title
* #property int $id
*/
class News extends Scripts\BaseObject
{
/**
* #ORM\Id
* #ORM\Column(type="integer");
* #ORM\GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ORM\Column(type="string")
* #Admin\Model\sina(sina="sina")
*/
protected $artist;
/**
* #ORM\Column(type="string")
*/
protected $title;
}
You can do it. You need to create a new annotation class. Register that annotation with the annotation registry. Then you need to make an event listener for the LoadClassMetadata event, and use a Reader class to instert your extra data into FieldMappings.
Parts of this libary are very unfinished and broken, but have a look at the Readonly directory. It shows how to read and insert a new annotation (in this case it marks a field as Readonly - ie no updates to that field allowed). SdsDoctrineExtensions

Categories