Zend Framework 2: How can I use my Abtract model for extending a model? - zend-framework2

I have a project with structure: https://docs.google.com/file/d/0B6hBvUW6YcomNHZJYUxvbTgxNkE
This is my AbstractTable.php:
namespace AdminManage\Model;
use Zend\Db\Adapter\Adapter;
use Zend\ServiceManager\ServiceLocatorInterface;
class AbstractTable{
protected $tablegateway;
protected $table;
protected $serviceLocator;
protected $adapter;
public function __construct(TableGateway $tableGateway) {
$this->tableGateway = $tableGateway;
$this->table = $this->tableGateway->getTable();
}
public function setServiceLocator(ServiceLocatorInterface $serviceLocator){
$this->serviceLocator = $serviceLocator;
return $this;
}
public function getServiceLocator(){
return $this->serviceLocator;
}
public function setDbAdapter(Adapter $adapter){
$this->adapter = $adapter;
return $this;
}
public function getDbAdapter(){
return $this->adapter;
}
public function fetchAll(){
return $this->tablegateway->select();
}
public function getTable(){
if(!$this->table)
$this->table = $this->tableGateway->getTable();
return $this->table;
}
}
This is my CategoryTable.php:
namespace Category\Model;
use Zend\Db\Sql\Sql;
use AdminManage\Model\AbstractTable;
class CategoryTable extends AbstractTable {
public function getListCategory() {
$adapter = $this->getDbAdapter ();
$sql = new Sql ( $adapter );
$select = $sql->select ( array (
"c" => "category"
) )->join ( array (
"cd" => "category_description"
), "c.category_id = cd.category_id" );
echo $sql->prepareStatementForSqlObject ( $select )->getSql ();
}
}
When I call getListCategory() in the controller, has an error:
Fatal error: Class 'AdminManage\Model\AbstractTable' not found in D:\xampp\htdocs\dokusyu\htdocs\admin\dokusyu_be\module\Course\src\Category\Model\CategoryTable.php on line 5.
How can I fix this error? Thank you!

ZF2 refer all files from root folder of your host, try creating a subdomain and and copy the files and access the pages

Related

zf2 - Nested Aggregate Hydrators

Is it possible to nest aggregate hydrators? If i have the following classes:
class Appointment{
public date;
public startTime;
public endTime;
public User; //* #var User */
}
class User{
public Location; //* #var Location*/
}
...being populated with the following AggregateHydrator (created from a factory):
class AppointmentModelHydratorFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator) {
$serviceManager = $serviceLocator->getServiceLocator();
$arrayHydrator = new ArraySerializable();
$arrayHydrator->addStrategy('date', new DateTimeStrategy())
->addStrategy('endTime', new TimeStrategy())
->addStrategy('startTime', new TimeStrategy());
$aggregateHydrator = new AggregateHydrator();
$aggregateHydrator->add($arrayHydrator);
$aggregateHydrator->add($serviceLocator->get('Hydrator\User'));
return $aggregateHydrator;
}
}
With the UserHydratorFactory looking like:
class UserHydratorFactory implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator) {
$sm = $serviceLocator->getServiceLocator();
$userHydrator = new UserHydrator($sm->get('User\Mapper'));
$aggregateHydrator = new AggregateHydrator();
$aggregateHydrator->add($userHydrator );
$aggregateHydrator->add($sm->get('HydratorManager')->get('Hydrator\User\Location'));
return $aggregateHydrator;
}
}
This is throwing an expection as the model is being returned as null, but if i comment out adding the Location hydrator to the User hydrator, it works fine (albeit without location data loaded). So i was wondering if aggregate hydrators are able to be nested?
It is not built-in, but doable.
namespace Hydrator;
use Zend\Stdlib\Hydrator\HydratorInterface;
class NestedHydrator implements HydratorInterface
{
protected $inner_hydrator;
private $empty;
public function __construct ($inner_hydrator, $empty)
{
$this->inner_hydrator = $inner_hydrator;
$this->empty = $empty;
}
public function extract ($object)
{
return [
$this->getPath() => $this->inner_hydrator->extract ($object->{$this->getPath()})
];
}
public function hydrate (array $data, $object)
{
$object->{$this->getPath()} = $this->inner_hydrator->hydrate ($data [$this->getPath()], $this->empty);
return $object;
}
protected function getPath ()
{
return get_class ($this->empty);
}
}
And then:
$u = new User();
$u->Location = "4 Clinton Rd.";
$a = new Appointment();
$a->date = "yesterday";
$a->startTime = "7:00";
$a->endTime = "8:00";
$a->User = $u;
$h = new AggregateHydrator();
$h->add (new ObjectProperty());
$nested = new \Hydrator\NestedHydrator(new ObjectProperty(), new User());
$h->add ($nested);
$data = $h->extract ($a);
$b = $h->hydrate ($data, new Appointment());
$this->assertEquals ($a, $b);

ZF2 tablegateway on select shows error "unknown column"

Title says it.
It says that i dont have a columnd 'user_id' but i have. It works with 'id'.
This is the problem function :
public function getUploadsByUserId($userId)
{
$userId = (int) $userId;
$rowset = $this->tableGateway->select(
array('user_id' => $userId));
return $rowset;
}
This is the model:
namespace Users\Model;
use Zend\View\Model\ConsoleModel;
class Upload
{
public $id;
public $filename;
public $label;
public $user_id;
public function getArrayCopy()
{
return get_object_vars($this);
}
function exchangeArray($data)
{
$this->id = (isset($data['id'])) ? $data['id'] : null;
$this->filename = (isset($data['filename'])) ? $data['filename'] : null;
$this->label = (isset($data['label'])) ? $data['label'] : null;
$this->user_id = (isset($data['user_id'])) ? $data['user_id'] : null;
}
}
Where can be the problem here, its clearly that i have such column.
The problem was that i was not configured the tablegateway correctly. It was 'user' instead of 'uploads' .
'UploadTableGateway' => function ($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$resultSetPrototype = new ResultSet();
$resultSetPrototype->setArrayObjectPrototype(new Upload());
return new TableGateway('uploads', $dbAdapter, null,
$resultSetPrototype);
},

ZF2 TableGateway join

I am in the process of trying to learn OO/Zend Framework over standard PHP.. I want to scream and write a mysql query instead of using the TableGateway method.
I have been following tutorials and have successfully printed out a table and some fields, although with the way I have gone about doing this, I am totally lost in how I should make this a join with another table and print out some fields there.
For example.
Table Fields
customer Idx, Company
contact Idx, First_Name
This is my customersController where I assume the work is carried out
namespace Customers\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Zend\DB\TableGateway\TableGateway;
class CustomersController extends AbstractActionController
{
protected $customersTable;
public function indexAction()
{
return new ViewModel(array('customer' => $this->getCustomersTable()->select()));
//return new ViewModel(array('customers' => $this->fetchJoin()->select()));
}
public function addAction()
{
}
public function editAction()
{
}
public function deleteAction()
{
}
public function getCustomersTable()
{
if (!$this->customersTable) {
$this->customersTable = new TableGateway (
'customer', //table name
$this->getServiceLocator()->get('Zend\DB\Adapter\Adapter')
);
}
return $this->customersTable;
}
}
Am I on the right track here?
If you need to make joins read about Zend\Db\Sql and Zend\Db\Select
which you can read about here
http://framework.zend.com/manual/2.0/en/modules/zend.db.sql.html
An example would be:
In your model(that extends the TableGateway or the AbstractTableGateway)
in Some function you can have something like(this is from a project) :
$sql = new \Zend\Db\Sql\Sql($this->getAdapter());
$select = $sql->select()
->from('event_related_events')
->columns(array())
->join('event_invitees', 'event_invitees.event_id =
event_related_events.related_event_id')
->where(array('event_related_events.event_id' => $eventId));
$selectString = $sql->getSqlStringForSqlObject($select);
$results = $this->getAdapter()->query($selectString, \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);
Then you can loop over the results and do what you need to.
Taking a look at more powerful ORM like Doctrine or Propel may also help, but may be an overkill for a small/hobby project.
EDIT: Answer for what was asked in comments
For Using expression(if, case etc) directly you can use something like :
$sql->select()
->from('table')
->columns(array(
'sorter' => new Expression('(IF ( table.`something` >= 'otherthing', 1, 0))'),
'some_count' => new Expression('(count(*))'),
)
)
Explaining the last line in SQL terms, it would be:
count(*) AS some_count
So this is my controller, basically from the Album example but now it will display customers from the customer table.
<?php
namespace Customers\Controller;
use Zend\Mvc\Controller\AbstractActionController;
use Zend\View\Model\ViewModel;
use Customers\Model\Customers;
use Customers\Form\CustomersForm;
class CustomersController extends AbstractActionController
{
protected $customersTable;
public function indexAction()
{
return new ViewModel(array(
'customer' => $this->getCustomersTable()->fetchAll(),
));
}
public function addAction()
{
}
public function editAction()
{
}
public function deleteAction()
{
}
public function getCustomersTable()
{
if (!$this->customersTable) {
$sm = $this->getServiceLocator();
$this->customersTable = $sm->get('Customers\Model\CustomersTable');
}
return $this->customersTable;
}
}
?>
The indexAction calls the getCustomersTable method which goes to the model (CustomersTable) and executes the "query" there.
<?php
namespace Customers\Model;
use Zend\Db\TableGateway\TableGateway;
class CustomersTable
{
protected $tableGateway;
public function __construct(TableGateway $tableGateway)
{
$this->tableGateway = $tableGateway;
}
public function fetchAll()
{
$resultSet = $this->tableGateway->select();
return $resultSet;
}
public function getCustomers($id)
{
}
public function saveCustomers(customers $customers)
{
}
public function deleteCustomers($id)
{
}
}
?>
So from your example, I should be trying to implement this into the fetchAll in the model?
Thanks for the help.
$sql = new \Zend\Db\Sql\Sql($this->getAdapter());
$select = $sql->select()
->from('customer')
->columns(array())
->join('contact', 'contact.Idx = customer.Idx')
->where(array('contact.Idx' => $eventId));
$selectString = $sql->getSqlStringForSqlObject($select);
$results = $this->getAdapter()->query($selectString, \Zend\Db\Adapter\Adapter::QUERY_MODE_EXECUTE);

injecting ServiceLocator via ServiceLocatorAwareInterface doesnt work

i read that implementing: ServiceLocatorAwareInterface will inject the serviceLocator to the same class.
So I got this:
Class MyModel implements ServiceLocatorAwareInterface {
protected $serviceLocator;
public function setServiceLocator(ServiceLocatorInterface $serviceLocator)
{
$this->serviceLocator = $serviceLocator;
}
public function getServiceLocator()
{
return $this->serviceLocator;
}
}
But $this->serviceLocator is always NULL
Do i have to do more than that?
You have to register your model in Service Config and retrieve it using service manager.
Here is an example:
/* Module.php */
public function getServiceConfig() {
return array(
'invokables' => array(
'my_model' => 'Application\Model\MyModel'
)
);
}
/* IndexController.php */
public function indexAction() {
$model = $this->getServiceLocator()->get('my_model');
$sl = $model->getServiceLocator(); // returns ServiceLocator
}

ZendFramework2 AbstractTableGateway getSql

I got a ZF2 project with 2 Models PosTable/TopTable which extend AbstractTableGateway.
I want to Paginate results from those Tables so i have a Pagination function in both of them.
this is what the PosTable Model looks like:
...
class PosTable extends AbstractTableGateway {
public function __construct($adapter) {
$this->table = 'pos';
$this->adapter = $adapter;
}
...
public function getPosPaginator($tid) {
$sql = $this->getSql();
$select = $sql->select();
$select->where('tid = '.$tid)->where('deleted = 0')->order('crdate ASC');
$adapter = new \Zend\Paginator\Adapter\DbSelect($select, $sql);
$paginator = new \Zend\Paginator\Paginator($adapter);
return $paginator;
}
...
which works perfectly.
but in my TopTable it looks the same like this:
...
class TopTable extends AbstractTableGateway {
public function __construct($adapter) {
$this->table = 'top';
$this->adapter = $adapter;
}
public function getTopPaginator($fid) {
$sql = $this->getSql();
$select = $sql->select();
$select->where('fid = '.$fid)->where('deleted = 0');
$adapter = new \Zend\Paginator\Adapter\DbSelect($select, $sql);
$paginator = new \Zend\Paginator\Paginator($adapter);
return $paginator;
}
...
my controller looks like this for PosTable:
...
public function posAction(){
...
$pos = $this->getPosTable()->getPosPaginator($tid);
$pos->setCurrentPageNumber($pageid)->setItemCountPerPage(19);
... return $pos etc...
same controller topAction:
...
public function topAction(){
...
$top = $this->getTopTable()->getTopPaginator($fid);
$top->setCurrentPageNumber($pageid)->setItemCountPerPage(20);
...return $top etc..
in that controller i got also these functions:
public function getTopTable(){
return $this->getServiceLocator()->get('Application\Model\TopTable');
}
public function getPosTable(){
return $this->getServiceLocator()->get('Application\Model\PosTable');
}
PosTable Pagination works perfectly, but the TopTable Pagination doesnt work.
i get this error:
Fatal error: Call to a member function select() on a non-object in ....
seems like
$sql = $this->getSql();
doesnt return the object.
how can i solve this problem?
one works one doesnt for no obvious reason.
my module.php looks like this:
namespace Application;
class Module
{
public function getAutoloaderConfig()
{
return array('Zend\Loader\StandardAutoloader' =>
array('namespaces' =>
array(__NAMESPACE__ => __DIR__ . '/src/' . __NAMESPACE__,),
),
);
}
public function getConfig()
{
return include __DIR__ . '/config/module.config.php';
}
public function getServiceConfig()
{
return array(
'factories' => array(
'Application\Model\TopTable' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$table = new \Application\Model\TopTable($dbAdapter);
return $table;
},
'Application\Model\ForTable' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$table = new \Application\Model\ForTable($dbAdapter);
return $table;
},
'Application\Model\PosTable' => function($sm) {
$dbAdapter = $sm->get('Zend\Db\Adapter\Adapter');
$table = new \Application\Model\PosTable($dbAdapter);
return $table;
},
),
);
}
}
Ok, after going through TableGateway Code and your extended class, I found the your implementation is not calling initialize which setup the sql object try to call the parent table gateway, below is the modified constructor for your PosTable and TopTable
/* for PosTable */
class PosTable extends TableGateway {
public function __construct($adapter) {
parent::__construct('pos', $adapter);
}
...
/* for TopTable */
class TopTable extends TableGateway {
public function __construct($adapter) {
parent::__construct('top', $adapter);
}
...

Resources