Yii CActiveDataProvider with class argument? - php

I found this code at this website. What would have to be in the $dp dataprovider for the class TotalColumn to be called in the CGridView? Do I have to have the class TotalColumn be somewhere in $dp? Any idea how I would declare that CActiveDataProvider?
<?php
// protected/views/inventory/index.php
Yii::import('zii.widgets.grid.CGridColumn');
class TotalColumn extends CGridColumn {
private $_total = 0;
public function renderDataCellContent($row, $data) { // $row number is ignored
$this->_total += $data->quantity;
echo $this->_total;
}
}
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider' => $dp, // provided by the controller
'columns' => array(
'id',
'name',
'quantity',
array(
'header' => 'Total',
'class' => 'TotalColumn'
)
)));
Here is my code, but nothing in my custom column is displayed:
Yii::import('zii.widgets.grid.CGridColumn');
class TotalSkills extends CGridColumn
{
private $test = "blah";
public function renderSkills($row, $data)
{
echo $this->test;
}
}
// People
echo CHtml::label('People', 'yw0', $shared_html_options);
$dataProvider = new CActiveDataProvider('Person');
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
'name',
'age',
array(
'header'=>'Total Skills',
'class'=>'TotalSkills'
)
)
));

You should create the TotalColumn class inside your protected/components directory as a TotalColumn.php file. That way you can use it in many different view files, instead of the view file that is defined only. Yii will load it automatically then.
$dp should be a typical DataProvider class (more likely a CActiveDataProvider) that is defined in your controller and passed to your view. The DataProvider can be as easy as the CGridView documentation describes it.

public function renderDataCellContent($row, $data)
is defined method in gridview
but there is no method such as
public function renderSkills($row, $data)
in gridview

Related

Call to a member function selectID() on null (Concrete CMS 8.5.7)

I need a new form select to allow me to set a different id and name in a select form. So I am trying to extend the form class. I did the following.
concrete\packages\concrete_form_addon\src\Concrete\Form\Service\Form2.php
namespace Concrete\Package\ConcreteFormAddon\Form\Service;
class Form2 extends \Concrete\Core\Form\Service\Form {
public function selectID($key, $optionValues, $valueOrMiscFields = '', $miscFields = []) {
working code for the option
}
}
Then in the class file I have
namespace Concrete\Package\ConcreteFormAddon;
use Concrete\Core\Asset\Asset;
use Concrete\Core\Asset\AssetList;
use Concrete\Core\Package\Package;
use Concrete\Core\Page\Page;
use Concrete\Core\Support\Facade\Route;
use Concrete\Core\Support\Facade\Config;
use Whoops\Exception\ErrorException;
class Controller extends Package {
protected $pkgHandle = 'concrete_form_addon';
protected $appVersionRequired = '8.4';
protected $pkgVersion = '0.8.7';
protected $pkgAutoloaderRegistries = [
'src/Concrete/Form' => 'Concrete\Package\ConcreteFormAddon\Form',
];
public function getPackageDescription() {
return 'Add custom form functions to Concrete CMS';
}
public function getPackageName() {
return 'Concrete Form Add-On';
}
}
Then the line of code that calls it:
<?= $form2->selectID('', $manufacturers, $product->getManufacturer() ? $product->getManufacturer()->getID() : '', ['id' => 'pManufacturer' . $pID, 'name' => 'pManufacturer[]', 'class' => 'selectize pricing-fields']) ?>
If I put the first bit of code in the core file it works fine if I use $form->selectID so there is something wrong with the way I'm setting up the class I believe.

How to point to a different Controller of a Model in CakePHP

I have one Model class named 'Name' and one Controller class named 'Controller1'. I have created a form using 'Name' model which is by default pointing to 'names' controller as per default naming convention of cakephp. But i want it to point to 'Controller1' controller..
I've replace this code:-
<?php echo $this->Form->create('Name'); ?>
with this one to see if it works:-
<?php
echo $this->Form->create('Name',array('controller'=>'Controller1',
'action'=>'view'));
?>
But it is not working and is pointing to 'names' controller only.
How can i point it to 'Controller1' instead of 'names' controller?
More details:-
Model (Name.php):-
class Name extends AppModel{
public $useTable = "tbl_names";
}
Controller (Controller1Controller.php):-
class Controller1Controller extends AppController
{
public function index(){
}
public function view($id){
$name ='';
if($this->request->is('post')){
$name = $this->request->data('name');
if($name==="xyz"){
$this->redirect('http://www.google.com');
}else{
$this->Save($this->request->data);
$this->request->data['name']= 'Nice';
}
}
return $id;
}
// Save to database if entered name is other than 'xyz'
private function Save($data){
$this->Name->create();
}
public function viewname($id,$name){
}
}
You have to set url key to pass crontroller and action values.
echo $this->Form->create(false, array(
'url' => array('controller' => 'recipes', 'action' => 'add'),
'id' => 'RecipesAdd'
));
See FormHelper > Options for create()

Zend Framework 2: Create Search Widget for Layout

I have a small private Project to learn ZF2. I have integrated Zend Lucene as a Search Function. This works well, but I now want to integrate a Search Field in my Layout, so that it is available on all pages. I am really not sure how to achieve this. First of all, am I correct that this is done with a View Helper? As you can see below, I have got no idea what I have to enter into the __invoke() of my Helper to display my Search Form. Is my way correct in general or is there a better way? I would like a good ZF2 solution, can someone give me some advice? Thank you very much in advance.
Okay, what have I done so far:
1. I created a Form:
namespace Advert\Form;
use Zend\Form\Form;
class SearchForm extends Form
{
public function __construct()
{
parent::__construct('search');
$this->setAttribute('method', 'post');
$this->add(array(
'name' => 'query',
'attributes' => array(
'type' => 'text',
'id' => 'queryText',
'required' => 'required'
),
'options' => array(
'label' => 'Search String',
),
));
$this->add(array(
'name' => 'submit',
'attributes' => array(
'type' => 'submit',
'value' => 'Search'
),
));
}
}
2. created a View Helper DisplaySearchForm.php !!! 2. UPDATE !!!
A BIG Thank you to AlexP for his help !!!
namespace Advert\View\Helper;
use Zend\View\Helper\AbstractHelper;
use Zend\Form\ElementInterface;
class DisplaySearchForm extends AbstractHelper
{
protected $form;
public function __construct($form)
{
$this->form = $form;
}
public function __invoke($form = null)
{
if ($form) {
$this->form = $form;
}
return $this->render($this->form);
}
public function render($form)
{
// return $this->getView()->form($form);
// To use my own Style, I have added a Partial
return $this->getView()->render('partial/search', array('form' => $form));
}
}
I read somewhere that it would not be good to use the ServiceLocator in the Helper, so I thought about doing that in a Factory, where I will then get the Form. So I created a Factory (not sure the Factory is right)
3. created Factory
namespace Advert\View\Helper;
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class DisplaySearchFormFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator) {
$realServiceLocator = $serviceLocator->getServiceLocator();
$form = $realServiceLocator->get('FormElementManager')->get('\Advert\Form\SearchForm');
$helper = new DisplaySearchForm($form);
return $helper;
}
}
4. I registered the Factory in the module.php
public function getViewHelperConfig()
{
return array(
'factories' => array(
'displaySearchForm' => 'Advert\View\Helper\DisplaySearchForm',
)
)
}
5. In my Layout layout.phtml
<?php echo $this->displaySearchForm(); ?>
The AbstractHelper has a getView() which returns the 'renderer'. This means you can use all the view helpers you need, as if you were in a view script.
The new helper could look like this.
use Zend\Form\ElementInterface;
class DisplaySearchForm extends AbstractHelper
{
protected $element; // Form element to render
public function __construct(ElementInterface $element)
{
$this->element = $element;
}
public function __invoke($element = null)
{
if ($element) {
$this->element = $element;
}
return $this->render($this->element);
}
public function render(ElementInterface $element)
{
return $this->getView()->form($element);
}
}

CakePHP Unit testing controller returning undefined variable

I am new to the Unit Testing portion of CakePHP. There is no better time to learn than now.
I have ready through all of the documentation and numerous tutorials on the web. I have run up against a snag during the completion of some of my more basic unit tests.
My Controller:
class TestsController extends AppController {
public $components = array('RequestHandler', 'Security');
public $helpers = array('Js');
public $uses = array('Tests');
public function beforeFilter() {
$this->layout = 'admin';
parent::beforeFilter();
}
/**
* Returns database values of all tests that have been created.
*
*/
public function index() {
if ($this->request->is('requested')) {
return $tests;
}
$this->paginate = array(
'fields' => array('id', 'name', 'email', 'access_token', 'access_token_begins',
'filesizelimit', 'related_files', 'access_token_expires'),
'limit' => 10,
'order' => array(
'created' => 'desc'
));
$this->set('tests', $this->paginate('Test'));
}
My Controller test looks like this:
class TestsControllerTest extends ControllerTestCase {
public $fixtures = array('app.test');
public function testIndex() {
$result = $this->testAction('tests/index');
debug($result);
}
}
The output of my test is:
PHPUNIT_FRAMEWORK_ERROR_NOTICE
Undefined variable: tests
Test case: testsControllerTest(testIndex)
The only viable solution to the error I am receiving would be that maybe the test controller needs authentication before it can actually run the testAction() ?
This is a very simple sample from the CakePHP Documentation guide, yet I receive and undefined variable error. Any help is greatly appreciated.
I have managed to answer my own question.
The $tests variable is undefined because of the if statement within the controller:
public function index() {
if ($this->request->is('requested')) {
return $tests;
}
$this->paginate = array(
'fields' => array('id', 'name', 'email', 'access_token', 'access_token_begins',
'filesizelimit', 'related_files', 'access_token_expires'),
'limit' => 10,
'order' => array(
'created' => 'desc'
));
$this->set('tests', $this->paginate('Test'));
}
That statement does not get hit when running the application, but it does when running the test. In this given function there is no need for the IF statement and therefore my error of UNDEFINED VARIABLE is now resolved.

Zend Framework 2: Database connection in view helper

I found a few other posts relevant to this issue, however i wasn't able to achieve what i wanted so i decided to delete everything and start over with some help...
This is my work so far, which does the job but the data are provided hard coded in an array and i need to create a database connection to fetch those data.
In my module class i have:
public function getViewHelperConfig()
{
return array(
'factories' => array(
'liveStreaming' => function() {
return new LiveStreaming();
},
),
);
}
This is the code i have in my view helper:
namespace Application\View\Helper;
use Zend\View\Helper\AbstractHelper;
class LiveStreaming extends AbstractHelper
{
protected $liveStreamingTable;
public function __invoke()
{
$events = array(
'1' => array('name' => 'Event name',
'sport' => 'Soccer',
'time' => '11:30'),
'2' => array('name' => 'Event name',
'sport' => 'Soccer',
'time' => '17:00'),
);
return $events;
//this is what should be used (or something like that) to get the data from the db...
//return array('events' => $this->getLiveStreamingTable()->fetchAll() );
}
public function getLiveStreamingTable()
{
if (!$this->liveStreamingTable) {
$sm = $this->getServiceLocator();
$this->liveStreamingTable = $sm->get('LiveStreaming\Model\LiveStreamingTable');
}
return $this->liveStreamingTable;
}
}
So, i want to get the $events array from the database. I've created Application\Model\LiveStreaming and Application\Model\LiveStreamingTable (following the instructions of the ZF2 official tutorial) and i need some help proceeding to the next step, which should probably have to do with the service locator.
You seem to be almost there. The only thing missing is the ability to call $this->getServiceLocator(); from within the view helper (as the AbstractHelper doesn't provide this method).
There are two options
Inject the LiveStreamingTable into the view helper directly
inject the ServiceManager itself and create the LiveStreamingTable within the helper
Option 1 Make LiveStreamingTable a dependency of the view helper (type hint in constructor)
namespace Application\View\Helper;
use Zend\View\Helper\AbstractHelper;
use LiveStreaming\Model\LiveStreamingTable;
class LiveStreaming extends AbstractHelper
{
protected $liveStreamingTable;
public function __construct(LiveStreamingTable $liveStreamingTable)
{
$this->liveStreamingTable = $liveStreamingTable;
}
public function getLiveStreamingTable()
{
return $this->liveStreamingTable;
}
}
And the factory becomes:
public function getViewHelperConfig()
{
return array(
'factories' => array(
'liveStreaming' => function($sl) {
// Get the shared service manager instance
$sm = $sl->getServiceLocator();
$liveStreamingTable = $sm->get('LiveStreaming\Model\LiveStreamingTable');
// Now inject it into the view helper constructor
return new LiveStreaming($liveStreamingTable);
},
),
);
}
Option 2 - Implement the ServiceLocatorAwareInterface (making it again a dependency of the view helper)
namespace Application\View\Helper;
use Zend\View\Helper\AbstractHelper;
use Zend\ServiceManager\ServiceLocatorAwareInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class LiveStreaming extends AbstractHelper implements ServiceLocatorAwareInterface
{
protected $serviceLocator;
protected $liveStreamingTable;
public function __construct(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function setServiceLocator(ServiceLocatorInterface $serviceLocator);
public function getServiceLocator();
public function getLiveStreamingTable()
{
if (null == $this->liveStreamingTable) {
$this->liveStreamingTable = $this->getServiceLocator()->get('LiveStreaming\Model\LiveStreamingTable');
}
return $this->liveStreamingTable;
}
}
Your factory will then look like:
public function getViewHelperConfig()
{
return array(
'factories' => array(
'liveStreaming' => function($sl) {
// Get the shared service manager instance
$sm = $sl->getServiceLocator();
// Now inject it into the view helper constructor
return new LiveStreaming($sm);
},
),
);
}
Personally, I feel that Option 1 makes more sense from a Dependency Injection (DI) point of view - It's clear that the LiveStreamingTable is what is needed to create the view helper.
Edit
Make sure you have the LiveStreaming\Model\LiveStreamingTable service also registered with the service manager (as we request it in the above code when we did $sm->get('LiveStreaming\Model\LiveStreamingTable');)
// Module.php
public function getServiceConfig()
{
return array(
'factories' => array(
'LiveStreaming\Model\LiveStreamingTable' => function($sm) {
// If you have any dependencies for the this instance
// Such as the database adapter etc either create them here
// or request it from the service manager
// for example:
$foo = $sm->get('Some/Other/Registered/Service');
$bar = new /Directly/Created/Instance/Bar();
return new \LiveStreaming\Model\LiveStreamingTable($foo, $bar);
},
),
);
}

Categories