Is it possible to use Entity method inside Sonata Admin class? - sonata-admin

Is it possible to use inside Sonata Admin class an Entity method that is not getter of property?
I would like add to $listMapper->add('sum') ...
class OrderAdmin extends AbstractAdmin
{
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->add('sum') //Order::getSum()
...
... result of getSum()
class /Entity/Order{
...
public function getSum()
{
foreach ( ... ) {
$sum += ...
}
return $sum;
}

Simply use name of that method:
$listMapper
->add('getSum',null, ['label'=>'Sum'])

Related

CakePHP3 - Cookie Value not being kept

I have a problem where the value for the cookie I set is not being kept if switching to a different section (controller) with CakePHP3.
I establish the original cookie in the AppController so it is sitewide:
<?php
namespace App\Controller;
use Cake\Controller\Controller;
use Cake\Event\Event;
use Cake\Http\Cookie\Cookie;
use Cake\Http\Cookie\CookieCollection;
class AppController extends Controller
{
public function initialize()
{
parent::initialize();
$this->loadComponent('RequestHandler');
$this->loadComponent('Flash');
$this->loadComponent('Cookie');
//set up initial cart cookie
$this->response = $this->response->withCookie(
(new Cookie('cart'))
->withPath('/')
->withValue(json_encode([]))
->withExpiry(new \DateTime('+1 month'))
);
}
I then have it set up in the CartController to add selected items to the cart cookie:
<?php
// src/Controller/CartController.php
namespace App\Controller;
use Cake\I18n\Time;
use Cake\Http\Cookie\Cookie;
use Cake\Http\Cookie\CookieCollection;
class CartController extends AppController
{
public function index()
{
$cart = json_decode($this->request->getCookie('cart'));
$add_cart = ($this->request->getQuery('add') == null ? [] : $this->request->getQuery('add'));
if (count($add_cart) > 0) {
foreach($add_cart as $ac) {
if(!in_array($ac, $cart)) {
$cart[] = $ac;
}
}
}
//replace cookie
$this->response = $this->response->withCookie(
(new Cookie('cart'))
->withPath('/')
->withValue(json_encode($cart))
->withExpiry(new \DateTime('+1 month'))
);
$this->loadModel('Books');
$cart_items = [];
foreach($cart as $cartp) { //'contain' => ['BookTypes'],
$book = $this->Books->get($cartp, ['fields' => array('id','name','description')]);
$cart_items[] = $book;
}
$this->set(compact('cart_items'));
}
If I stay within "Cart", the cookie keeps the value. However, as soon as I move to any other page (home page or browsing books), the cookie value is reset to empty (an empty array).
What is causing this?
I found my problem.
Had to move the initial cookie from the initialize() to beforeFilter() in AppController.php and now it seems to be working.

Codeigniter autocheck db depending on session value

I'm trying to force my app to check every time it loads a model or controller depending on which is my session value.
This is actually running, but just when I get throw this model.
class News_model extends CI_Model {
public function __construct()
{
parent::__construct();
if($this->session->dbname=='db1'){
$this->db=$this->load->database('db1', TRUE);
}
else{
$this->db=$this->load->database('db2', TRUE);
}
}
public function get_news($slug = FALSE)
{
if ($slug === FALSE)
{
$query = $this->db->get('news');
return $query->result_array();
}
$query = $this->db->get_where('news', array('slug' => $slug));
return $query->row_array();
}
}
But I do not war to include that __construct code to all my models or controllers.
I've tried to add on my autoload.php
$autoload['model'] = array('General');
Where my General code is something like this.
class General extends CI_Model {
function __construct()
{
parent::__construct();
if($this->session->dbname=='db1'){
$this->db=$this->load->database('db1', TRUE);
}
else{
$this->db=$this->load->database('db2', TRUE);
}
}
}
How can I do it?
You can do it by creating a base model which will be extended by your models that require the database check.
I have simplified the checking and loading code. A simple ternary determines the string to use and stores it in the variable $dbname. That variable is used to load the database, i.e. $this->load->database($dbname);.
I don't believe you need the second argument to load::database() which means you don't need to set $this->db explicitly. If I'm wrong, use
$this->db = $this->load->database($dbname, TRUE);
Below is the "base" model. The prefix of the file name is determined in config.php with the setting $config['subclass_prefix'] = 'MY_'; Adjust your base model's file and class name to match the 'subclass_prefix' you use.
/application/core/MY_Model.php
<?php
class MY_Model extends CI_Model
{
public function __construct()
{
parent::__construct();
$dbname = $this->session->dbname == 'db1' ? 'db1' : 'db2';
$this->load->database($dbname);
}
}
Use the above to create other models like so...
class News_model extends MY_Model
{
public function get_news($slug = FALSE)
{
if ($slug === FALSE)
{
$query = $this->db->get('news');
return $query->result_array();
}
$query = $this->db->get_where('news', array('slug' => $slug));
return $query->row_array();
}
}

Displaying array values in laravel 5.2

I have the following hasMany() relationship in App\User.php ,
public function partner_preference_occupation()
{
return $this-hasMany('App\Models\User\PartnerPreferenceOccupation', 'user_id');
}
The following is my PartnerPreferenceOccupation Model,
<?php
namespace App\Models\User;
use App\Models\BaseModel,
App\Models\ValidationTrait;
class PartnerPreferenceOccupation extends BaseModel {
use ValidationTrait;
public function __construct() {
parent::__construct();
$this->__validationConstruct();
}
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'partner_preferences_occupation';
protected $fillable = array('user_id', 'occupation_id');
protected $dates = array();
public $uploadPath = array();
protected function setRules() {
$this->val_rules = array();
}
protected function setAttributes() {
$this->val_attributes = array();
}
public function occupation_name() {
return $this->belongsTo('App\Models\Master\OccupationModel', 'occupation_id');
}
}
I want to display the array of occupation name in my view. I tried the following code, but it fails.
{{$obj->partner_preference_occupation ? $obj-partner_preference_occupation->occupation_name->name : null}}
The error is as follows,
Undefined property:Illuminate\Database\Eloquent\Collection::$occupation_name
How can I display them.Thanks in advance.
There is a typo in $obj-partner_preference_occupation->occupation_name->name
Should be $obj->partner_preference_occupation->occupation_name->name
Make sure that occupation_name exists in the collection. You can check by doing the following in your View:
dump( $obj->partner_preference_occupation );
It might help you identify where the issue lies.
Also, to display a collection as an array, you can use the toArray() method, e.g.:
$obj->partner_preference_occupation->toArray()
Ok I got it,
As it is an array of values to be fetched, I used foreach to display them in my view as,
#if($occ=$obj->partner_preference_occupation->lists('occupation_name'))
#foreach($occ as $oc)
{{$oc->name}}
#endforeach
#endif
occupatoin_name is the name of my relationship that I used in my model. And that worked for me :)

Symfony3 return array from query to json

I have problem, i can't return my posts array to json becouse symfony returns array with entity object?
Its my code:
public function indexAction()
{
$em = $this->getDoctrine()->getManager();
$posts = $em->getRepository('AppBundle:Post')->findAll();
return $this->json($posts);
}
I use $this->json is return json data, feature added on sf3.
But this is my result:
[
{},
{},
{}
]
i want to load my posts.
ps. i know, i can use Query builder, and method toArray or something, but is any method to use and DRY? Thx
Because entity can have multiple boundaries, proxy objects and related entities, I personally prefer to explicitly specify what is about to be serialized, like this:
use JsonSerializable;
/**
* #Entity
*/
class SomeEntity implements JsonSerializable
{
/** #Column(length=50) */
private $title;
/** #Column(length=50) */
private $text;
public function jsonSerialize()
{
return array(
'title' => $this->title,
'text' => $this->text,
);
}
}
And then it's as simple as json_encode($someEntityInstance);.
You can use JMSSerializerBundle as well to accomplish your task DRY.
Also, there is an option to write your own serializer to normalize the data.
UPDATE:
If you want multiple representations of a JSON, it can be achieved like this:
use JsonSerializable;
/**
* #Entity
*/
class SomeEntity implements JsonSerializable
{
// ...
protected $isList;
public function toList()
{
$this->isList = TRUE;
return $this;
}
private function jsonSerializeToList()
{
return [ // array representing list... ]
}
public function jsonSerialize()
{
if( $this->isList ) {
$normalized = $this->jsonSerializeToList();
} else {
$normalized = array(
'title' => $this->title,
'text' => $this->text,
);
}
return $normalized;
}
}
And called as json_encode($someEntityInstance->toList());. Any way, this is a bit dirty, so I suggest to be consistent with an idea of the interface.
A best solution is to enable the serializer component in Symfony:
#app/config/config.yml
framework:
serializer: ~
Note: the serializer component is disabled by default, you have to uncomment the config line in app/config/config.yml file.

Zend framework 2 model for database, separate model for each table?

I looked through the manual of Zend Framework 2 about creating model to managing operations on table. Is the class with method exchangeArray() is necessary? It's only copy data :/ Can i create one model to manage a few tables?
I created two classes:
namespace Application\Model;
use Zend\Db\Adapter\Adapter;
use Zend\Db\Adapter\AdapterAwareInterface;
abstract class AbstractAdapterAware implements AdapterAwareInterface
{
protected $db;
public function setDbAdapter(Adapter $adapter)
{
$this->db = $adapter;
}
}
and:
namespace Application\Model;
class ExampleModel extends AbstractAdapterAware
{
public function fetchAllStudents()
{
$result = $this->db->query('select * from Student')->execute();
return $result;
}
}
I also add entries in Module.php:
'initializers' => [
'Application\Model\Initializer' => function($instance, \Zend\ServiceManager\ServiceLocatorInterface $serviceLocator){
if ($instance instanceof AdapterAwareInterface)
{
$instance->setDbAdapter($serviceLocator->get('Zend\Db\Adapter\Adapter'));
}
}
],
'invokables' => [
'ExampleModel' => 'Application\Model\ExampleModel'
],
I execute methods from model by:
$this->getServiceLocator()->get('ExampleModel')->fetchAllStudents();
You should do 2 things with your code. First, implement AdapterAwareInterface properly. Second, create an initializer which injects the adapter into your model. Consider the code below:
...
'initializers' => [
function($instance, ServiceLocatorInterface $serviceLocator){
if ($instance instanceof AdapterAwareInterface) {
$instance->setDbAdapter($serviceLocator->get('Zend\Db\Adapter\Adapter'));
}
}
]
...
abstract class AbstractModel implements AdapterAwareInterface
{
protected $db;
public function setDbAdapter(Adapter $adapter)
{
$this->db = adapter;
}
}
...
'invokables' => [
'ExampleModel' => 'Application\Model\ExampleModel'
]
As you can see from above, after all, you don't need a factory for each your model. You can either register invokables or create an Abstract Factory to instantiate your models. See an example below:
...
'abstract_factories' => [
'Application\Model\AbstractFactory'
]
...
class AbstractFactory implements AbstractFactoryInterface
{
public function canCreateServiceWithName(ServiceLocatorInterface $serviceLocator, $name, $requestedName)
{
return class_exists('Application\Model\'.$requestedName);
}
public function createServiceWithName(\Zend\ServiceManager\ServiceLocatorInterface $serviceLocator, $name, $requestedName)
{
$class = 'Application\Model\'.$requestedName();
return new $class
}
}
Hope this helps

Resources