I have a class for configuration on my script and I implement the config. I then want to use the options as an object reference like the following, but not sure how to get it all the way to the final object field and also how to make it recognize sub arrays too
class Configuration {
public $cookies = array(
"cookie_prefix" => "site_",
"site_settings" => array(
"domain" => "somesite.com",
"https_only" => TRUE
),
"another_item" => "and some data too"
);
}
$config = new Configuration();
echo $config->cookies->cookie_prefix;
echo $config->cookies->site_settings->domain;
Right now it works if I do the following
echo $config->cookies['cookie_prefix'];
echo $config->cookies['site_settings']['domain'];
But I want it to be an object all the way down. Can't wrap my brain around this one for some reason?
I know this is easily done - I am just missing the way how...
I just passed the items in the __construct as json and its working the way I wanted now, duh.
public $cookies = array(
"cookie_prefix" => "site_",
"site_settings" => array(
"domain" => "somesite.com",
"https_only" => TRUE
),
"another_item" => "and some data too"
);
public function __construct() {
$this->cookies = json_decode(json_encode($this->cookies));
}
Related
I'm trying to pass data about the page state (navbar links having active class when you are in that exact page), page title. I do so with an indexed array $pageInfo, however I am getting a syntax error and doen't know where?
Also do you think this is a good method or should I use view->share() instead?
public function clases()
{
$pageInfo[] =
(
'page_title' => 'Clases',
'menu_active' => 'CLases',
'sub_menu_active' => '',
);
return view('clases.list', compact('pageInfo'));
}
public function domicilio()
{
$pageInfo[] =
(
'page_title' => 'Clases a domicilio',
'menu_active' => 'Clases',
'sub_menu_active' => 'Clases a domicilio',
);
return view('clases.domicilio', compact('pageInfo'));
I suggest you read PHP basic syntax.
Basically you want to do this:
$pageInfo =
[
'page_title' => 'Clases',
'menu_active' => 'CLases',
'sub_menu_active' => '',
];
Arrays have a syntax of [key => val, ...] in PHP, you're using () as it seems.
Also $someArray[] = someValue, will append the someValue to an existing array, in your case that would create another, unwanted level of your array.
And last, you're not ending the domicilio() function. But I'll assume you just didn't paste it in (you should add } at the end, if that's not the case).
I need to understand the code below, specially how exactly $duplicateChecks and $relationCallbacks work but there is little explanation on the official documentation. Can somebody explain how these work or suggest some other documentation I can look at?
class PlayerCsvBulkLoader extends CsvBulkLoader {
public $columnMap = array(
'Number' => 'PlayerNumber',
'Name' => '->importFirstAndLastName',
'Birthday' => 'Birthday',
'Team' => 'Team.Title',
);
public $duplicateChecks = array(
'Number' => 'PlayerNumber'
);
public $relationCallbacks = array(
'Team.Title' => array(
'relationname' => 'Team',
'callback' => 'getTeamByTitle'
)
);
public static function importFirstAndLastName(&$obj, $val, $record) {
$parts = explode(' ', $val);
if(count($parts) != 2) return false;
$obj->FirstName = $parts[0];
$obj->LastName = $parts[1];
}
public static function getTeamByTitle(&$obj, $val, $record) {
return FootballTeam::get()->filter('Title', $val)->First();
}
}
$duplicateChecks is used by findExistingObject function in the CsvBulkLoader class. It is iterated over to find any object that has a column with the specified value. In that example, it checks the "PlayerNumber" column.
It can also be passed a callback like so:
public $duplicateCheck = array(
'Number' => array(
'callback' => 'checkPlayerNumberFunction'
)
);
The callback specified needs to either exist on an instance of the class specified on the property objectClass or on the CsvBulkLoader itself (which would happen if you extended it). These callbacks are used to do more complex duplicate lookups and return an existing object (if any) found.
$relationCallbacks on the other hand is used by the main processRecord function. The callback works in the same way as the $duplicateCheck callback, it needs to either exist on an instance of the class specified on the proeprty objectClass or on the CsvBulkLoader. These callbacks can return an object that will be related back to a specific object record (new or existing) as a has_one.
There is a little more to it than that though the best way to learn is by a bit of experimentation and jumping through the code of the class itself. I have linked to the various functions etc in my answer.
I have an Action method in Foo Controller which requires parameters:
public function fooAction($one, $two) {
$a = one;
$b = $two;
}
And I need to forward to that method from the other method of some Boo Controller. And one of those parameters has to be by reference parameter. The only example that the manual has is this:
$result = $this->forward()->dispatch('Boo\Controller\Boo', array('action' => 'boo'));
No any additional parameters. But they write:
$params is an optional array of parameters with which to see a
RouteMatch object for purposes of this specific request.
So, I tried:
$result = $this->forward()->dispatch('Boo\Controller\Boo', array(
'action' => 'boo',
'one' => &$one,
'two' => $two,
));
But it doesn't work.
Is there any way to pass additional parameters to forward controller?
UPD:
These do not work too:
$result = $this->forward()->dispatch('Boo\Controller\Boo', array(
'action' => 'boo',
'params' => array(
'one' => &$one,
'two' => $two,
)));
$result = $this->forward()->dispatch('Boo\Controller\Boo', array(
'action' => 'boo',
'options' => array(
'one' => &$one,
'two' => $two,
)));
UPD 2:
I still can't get the functionality I want (to pass parameters with the forward plugin) but I found other solutions. Before calling the forward plugin I set the variables to the Request object and after the forward I get them from the Request in my boo Action of my Boo\Controller\BooController:
// in Foo::fooAction
$this->getRequest()->one = &$one;
$this->getRequest()->two = $two;
$result = $this->forward()->dispatch('Boo\Controller\Boo', array('action' => 'boo'));
// in Boo::booAction
$a = $this->getRequest()->one;
$b = $this->getRequest()->two;
Stupid solution, it will not work with Ajax requests. Still interested how to pass parameters with the forward plugin. OR MAYBE how to get them in the booAction. Because there in no anything in the Request if I pass them with the forward.
UPD 3 and Final:
I finally found where they've decided to hide parameters I pass with the forward plugin. They put them in the RouteMatch object.
- Tryyyy to guess where we've hidden your params... Oh yeeah, they are in the RouteMatch, of course they are there, didn't you think smth else?
And NO ANY info in the forward plugin section of the manual!
To get params, I have to do this in my BooController::booAction:
$param = $this->getEvent()->getRouteMatch()->getParam('nameOfParam');
Why not to use the params plugin?
This works for me:
public function indexAction() {
$object = new SomeObject();
return $this->forward()->dispatch('Application\Controller\Index', [
'action' => 'show',
'myObject' => $object,
]);
}
public function showAction() {
$object = $this->params('myObject');
var_dump($object);
return [];
}
You can create a container class and use it in both controllers
in module.conf
public function getServiceConfig()
{
return array(
'invokables' => array(
'my_handy_container' => 'path\container_class_name',
)
);
}
Create a getter in both controllers:
public function getMyHandyContainer()
{
if (!$this->myHandyContainer) {
$this->myHandyContainer = $this->getServiceLocator()->get('my_handy_container');
}
return $this->myHandyContainer;
}
And call it using:
$myContainer = $this->getMyHandyContainer()->myHandyContainer;
$myContainer->foo = 5; // set something
ZF2 way to pass vars using forward
In the passing method do:
return $this->forward()->dispatch('controller_name', [
'action' => 'whatever',
'varname' => $value,
'varname2' => $value2
]);
In the invoked controller method, do:
$param2 = $this->params()->fromRoute('varname2',false);
Thought I would add another option that works for me.
You can simply pass the params straight through the forward function and use the routeMatch function to access them at the other end.
return $this->forward()
->dispatch('Module\Controller\Foo', array(
'action' => 'bas',
'id' => 6)
);
Passes to Foo Controller, basAction in this method you can then use the following code to access the id param
$myParam = (int) $this->getEvent()->getRouteMatch()->getParam('id');
Not sure if this meets your requirements - but works for me.
Thanks for the question, helped me a lot. Found an easy way for getting all params passed to forward()->dispatch(...). In the controller's action method:
$params = $this->params()->fromRoute();
returns array $data as passed as $data into forward()->dispatch($controllerName, $data).
Here in the official ZF2 documentation is written exactly how it works:
$params is an optional array of parameters with which to seed a RouteMatch object for purposes of this specific request. Meaning the parameters will be matched by their key to the routing identifiers in the config (otherwise non-matching keys are ignored).
So pass like this:
$params = array(
'foo' => 'foo',
'bar' => 'bar'
);
$this->forward()->dispatch('My\Controller', $params)
And then you can get your route match params in your My\Controller like normally:
$foo = $this->params()->fromRoute('foo');
$bar = $this->params()->fromRoute('bar');
For people struggling with accessing parameters within their controller here a nice overview from this CheatSheet.
$this->params()->fromPost('foo'); //POST
$this->params()->fromQuery('foo'); //GET
$this->params()->fromRoute('foo'); //RouteMatch
$this->params()->fromHeader('foo');//Header
$this->params()->fromFiles('foo'); //Uploaded file
I'm a little confused on how DI works with ZF2. I've spent the last couple of days trying to get my head around it. While I have made some progress a lot of it still baffles me...
Using this (http://akrabat.com/getting-started-with-zend-framework-2/) tutorial I managed to get a grasp that the following:
'di' => array('instance' => array(
'alias' => array(
'album' => 'Album\Controller\AlbumController',
),
'Album\Controller\AlbumController' => array(
'parameters' => array(
'albums' => 'Album\Model\Albums',
),
),
works because in our Album Controller class we have a setAlbum function. So when the DI class will call that setAlbums function and pass it the 'Album\Model\Albums' class.
Fine get that no problem..
Now let's look at this (which comes in the skeleton application off the zend site)
'Zend\View\HelperLoader' => array(
'parameters' => array(
'map' => array(
'url' => 'Application\View\Helper\Url',
),
),
),
Now i would expect there within the Zend\View\HelperLoader (or an inherited class) would contain a setMap() function that the DI class would pass an array. But this appears not to be the case. As I cannot find a setMap anywhere.
My question is first what am I not understanding about the way DI works with the ZF2... But also what does the code above (about zend\view\helper) actually do. I mean what does injecting 'map' => array('url' => 'Application\View\Helper\Url') into the Zend\View\HelperLoader actually do?
Thanks for any help anyone can give. I appreciate it's a beta framework and what answers I may get now not apply in a months time. But this all seems pretty fundamental and i'm just no getting it!
The DI configuration of ZF2 works indeed with the names of the arguments in the signature. It does not matter if this is done with a constructor or a explicit setter. The setter must, however, start with "set" to be recognized by Zend\Di\Di.
So if you have a class like this:
<?php
namespace Foo;
class Bar
{
public function __construct ($baz) {}
public function setSomethingElse ($bat) {}
}
You can inject both a $baz and a $bat:
'di' => array(
'instance' => array(
'Foo\Bar' => array(
'parameters' => array(
'baz' => 'Something\Here',
'bat' => 'Something\There',
),
),
),
)
For Zend\Di it does not matter what the function name exactly is, as long as it starts with "set" and the name of the argument is correct. That is why Foo\Bar::setSomethingElse($bat) works just like Foo\Bar::setBat($bat).
Just make sure you name your arguments correctly. For example, it is easy to do something like this:
<?php
namespace Foo;
class Bar
{
public function setCacheForBar ($cache) {}
public function setCacheForBaz ($cache) {}
}
But that will not work nicely together with Zend\Di.
I have a Product model for a multi site application.
Depending on the domain(site) I want to load different data.
For example instead of having a name and description fields in my database I have posh_name, cheap_name, posh_description, and cheap_description.
if I set something up like this:
class Product extends AppModel
{
var $virtualFields = array(
'name' => 'posh_name',
'description' => 'posh_description'
);
}
Then it always works, whether accessed directly from the model or via association.
But I need the virtual fields to be different depending on the domain. So first I creating my 2 sets:
var $poshVirtualFields = array(
'name' => 'posh_name',
'description' => 'posh_description'
);
var $cheapVirtualFields = array(
'name' => 'cheap_name',
'description' => 'cheap_description'
);
So these are my 2 sets, but how do I assign the correct one based on domain? I do have a global function called isCheap() that lets me know if I am on the lower end domain or not.
so I tried this:
var $virtualFields = isCheap() ? $this->cheapVirtualFields : $this->poshVirtualFields;
This gives me an error. Apparently you cannot assign variables in a Class definition like this.
So I put this in my Product model instead:
function beforeFind($queryData)
{
$this->virtualFields = isCheap() ? $this->cheapVirtualFields : $this->poshVirtualFields;
return $queryData;
}
This works ONLY when the data is accessed directly from the model, DOES NOT work when the data is accessed via model association.
There has got to be a way to get this to work right. How?
Well if I put it in the constructor instead of the beforeFind callback it seems to work:
class Product extends AppModel
{
var $poshVirtualFields = array(
'name' => 'posh_name',
'description' => 'posh_description'
);
var $cheapVirtualFields = array(
'name' => 'cheap_name',
'description' => 'cheap_description'
);
function __construct($id = false, $table = null, $ds = null) {
parent::__construct($id, $table, $ds);
$this->virtualFields = isCheap() ? $this->cheapVirtualFields : $this->poshVirtualFields;
}
}
However, I am not sure if this is a CakePHP no no that can come back to bite me?
seems like the issue could be that the model association is a model that is built on the fly. eg AppModel
try and do pr(get_class($this->Relation)); in the code and see what the output is, it should be your models name and not AppModel.
also try and use:
var $poshVirtualFields = array(
'name' => 'Model.posh_name',
'description' => 'Model.posh_description'
);
var $cheapVirtualFields = array(
'name' => 'Model.cheap_name',
'description' => 'Model.cheap_description'
);