Zend Db Table Abstract Manipulate select() - php

is there any chance to set a where statement on any select() request regarding a Zend Db Table Abstract Object?
Example:
We have 2 roles, 1 role 'admin' which is allowed to see all products and 1 role 'supplier' which is allowed to see only their own products.
I don't want to check the role and set the where statement for the Zend Db Table Abstract Object in every ActionController. Is there any chance to do this in the Zend Db Table Abstract?
class ProductsModel extends Zend_Db_Table_Abstract
{
protected $_name = 'artikel';
protected $_primary = 'ID';
protected $_where = ('supplier = ?', $this->_auth->Role ); # SOMETHING LIKE THAT ??
}
Thanks!
M.

There are two definitions in ZF: Model and Table. You should not substitute them. The model describes abstract layer between Controller and Table. The model may work with Table by means of Mapper where you can implement all business logic (where clauses, order, limit and so on).
It all are included into standart ZF example template.

Related

How to extend from Doctrine-Entity without Discriminator-Column

The challenge:
I want to re-use an existing entity of a third party bundle with class-inheritance in that way, that still only one table remains and no extra stuff will be necessary. That means: no discriminator-column and no JOINs.
Instead only the final most inherited class should be queryable, add some properties to the base entity and just use one table containing all columns, that are added to the entity from itself and thru inheritance.
To be clear here: I am not interested in classic table inheritance. I just want to extend a base class with additional columns in that way, that the table in the database represents the sum of all needed columns.
There is no need to be able to create an instance of the base entity.
For those who are interested, i explain the reason below.
Base entity of third party library:
Sylius\UserEntity (TableName: "sylius_user")
============================================
ColA, ColB, ColC
My class:
MyProject\UserEntity : Sylius\UserEntity (TableName: "user") <---- overwrite the base table name
========================================
ColD, ColE, ColF
The model above represents the final approach: my user entity extends syslius' user entity and should be persisted in and queried from the table "user" (instead of both "user" AND "sylius_user"), which contains all columns of the final extended entity:
The Table-Structure:
Thus, only one table would exist in my szenario.
Table "user":
=============
ColA, ColB, ColC, ColD, ColE, ColF
The first 3 columns are properties in base entity, and the last 3 columns are properties in "my" user entity which gots the first three thru inheritance.
What i did:
My user class looks like so:
use \Sylius\Component\User\Model\User as BaseUser;
/**
* User
*
* #ORM\Entity(repositoryClass="MyAppName\UserBundle\Repository\UserRepository")
* #ORM\Table(name="user", uniqueConstraints= ... */
class User extends BaseUser
{
The UserRepository:
class UserRepository extends EntityRepository
{
/**
* #param string $usernameOrEmail
* #return User
*/
public function findByUsernameOrEmail($usernameOrEmail)
{
$qb = $this
->createQueryBuilder('u')
->where('u.username = :search OR u.email = :search')
->setParameter('search', $usernameOrEmail);
try {
return $qb->getQuery()->getSingleResult();
}
catch(NoResultException $e) {
return null;
}
}
}
This query results in selecting columns from the table "user", but the query tries to select the columns twice each with a separate table alias. The resulting query fails because it is broken.
What Doctrine does here, looks like so:
SELECT s0.ColA, s0.ColB, s0.ColC,
u0.ColD, u0.ColE, u0.ColF
FROM user u0
As everyone can see, an additional table alias "s0" is used here without to reference it with a table. What i wanted doctrin to do, is:
SELECT u0.ColA, u0.ColB, u0.ColC,
u0.ColD, u0.ColE, u0.ColF
FROM user u0
Ho to achieve this?
For those who are interested in the purpose of this task:
We want to add sylius bundles to our long existing symfony application having already an own user-bundle with user model class and existing data out there.
So we'd like to extend the user class of sylius with adding our own properties to build a "bridge" between the sylius class and our user class. The difference between both is slim on the property-side and lies in only a few columns to rename and add some special properties and methods. But we have lots of relations from our user class to other entities, which wouldn't be an issue if we could doctrine get to ignore the table inheritance staff and just act as a plain class-re-using-thing here.
Is the base class a MappedSuperclass?
As long as the base class is defined as MappedSuperclass, you can simply extend the class and define the extending class as Entity.
Sylius defines the entities as a MappedSuperclass by default. A subscriber (LoadOrmMetadataSubscriber) passes each entity and sets MappedSuperclass to false if necessary, meaning it changes the MappedSuperclass to an Entity when the class is defined in the config.

Modeling an Object with one-to-many relationships (PHP)

I am trying to force myself to be consistent when modeling objects, but I'm just not sure what the best way is to create a class that has one-to-many relationships.
For example, lets say I have two tables in a database called Projects & Notes. A note can only belong to one project and a project can have many notes. Would the following be a good (best) way to model my project class? Or should the notes just be set to a separate variable in the controller and never be a property of project?
class Project extends BaseModel{
$id //string
$description //string
$notes //array of note objects
}
class Note extends BaseModel{
$id //string
$text//string
}
//In a Controller Class
$project = new Project();
$noteArray = new Note();
//Set the note property of project equal to an array of note objects
$project->setNotes($noteArray->findNotes($project->id));
I think there should be one more property in Note model that will reference to the Project model. Identificators of model MUST be an integer type
class Note extends BaseModel{
$id //string
$text//string
$project_id //int
}
So when you add a project, say it, with ID=5, You can add Notes with project_id = 5. And it will be one-to-many relatoionship.

Kohana 3 simple relations

I'm trying to write a very simple cms (for learning purposes) in kohana 3 web framework.
I have my db schemas and i want to map it to ORM but i have problems with relations.
Schemas:articles and categories
One article has one category. One category might has many articles of course.
I think it is has_one relationship in article table.(?)
Now php code. I need to create application/classes/models/article.php first, yes?
class Model_Article extends ORM
{
protected // and i am not sure what i suppose to write here
}
class Model_Article extends ORM{
protected $_belongs_to = array
(
'category' => array(), // This automatically sets foreign_key to category_id and model to Model_Category (Model_$alias)
);
}
class Model_Category extends ORM{
protected $_has_many = array
(
'articles' => array(), // This automatically sets foreign_key to be category_id and model to Model_Article (Model_$alias_singular)
);
}
You can also manually define the relation ;
'articles' => array('model'=>'article','foreign_key'=>'category_id');
More about Kohana 3 ORM
More about Kohana ORM naming conventions

The M of MVC (ZF)

I don't get it how it really works.
I have a database table user and a model User:
<?php
class User extends Zend_Db_Table_Abstract {
protected $_name = 'users';
}
And in the controller I call it: $user = new User()
But how do I get for example all users or a user with the id: 1?
Zend_Db_Table implements the Table Gateway pattern and the associated Zend_Db_Table_Row implements the Row Data Gateway pattern.
This means that as the table class represents your database table, it makes more sense to use a plural class name. Similarly, a singular class name should be used for the row class.
Hence you end up with something like this:
class Model_Users extends Zend_Db_Table_Abstract
{
protected $_name = 'users'; // database table name
protected $_rowClass = 'Model_User'; // row class name
public function fetchAllInLastNameOrder()
{
return $this->fetchAll(null, array('last_name', 'first_name'));
}
public function fetchUserById($id)
{
return $this->_fetchRow('id = '. (int)$id);
}
}
class Model_User extends Zend_Db_Table_Row_Abstract
{
public function getFullName()
{
return trim($this->title . ' '
. $this->first_name . ' '
. $this->last_name);
}
}
The point of creating your own classes is that you can add your own methods that your controllers and views can then use. You should never use the Zend_Db_Table methods directly other than in your model classes. This is because this model design is tightly coupled to the database implentation. Over time, you may find that this isn't flexible enough and want to use a different system. If you have ensured that the rest of your application only ever accesses methods created in Model_Users and Model_User then you should be able to reimplement your model without breaking the rest of your app...
For larger applications and ones with complex business logic, it is rare for a model to be a simple wrapper over a single database table. For better flexibility and maintainability, you can consider creating models which are simple classes and then using a mapper class that maps from the model to the database. This is explored by Matthew Weier O'Phinney in his talk Architecting Your Models, which I highly recommend looking at.
Also, for ideas on how to use the model from within the controller, the Quick Start or my tutorial are good starting points.
Are you looking for $user->find()?
Also, Zend_Db_Table != Model. You can read more about the M of MVC here:
Model Infrastructure
Zend Framework: Surviving the Deep End
Writing Robust PHP Backends with Zend Framework
Try creating a static method in your User class that returns an array of all users.

Zend Framework with multiple schema/databases?

I have a few tables that I've defined like the below examples:
class TableA extends Zend_Db_Table_Abstract
{
protected $_schema = 'schema1';
protected $_name = 'tablea';
}
class TableB extends Zend_Db_Table_Abstract
{
protected $_schema = 'schema2';
protected $_name = 'tableb';
}
This seems to work perfectly using one default Db adapter (since the 2 schemas are on the same server).
Code like this works:
$tableA = new TableA();
$select = $tableA->select();
// $select->__toString() outputs: SELECT * FROM `schema1`.`tablea`
However, when I try to use the same models with any of the Zend Framework table relationship functions (ie: findDependantRowset() or findManyToManyRowset()) the query tries to execute using the schema from the default adapter and does not use the appropriate schema that is defined in the model class.
Is this a bug? How can I force ZF to use the schema I have defined in the table class and not the one defined as the default in the default Db adapter?
I think this is related to this bug:
http://framework.zend.com/issues/browse/ZF-1838
It has been fixed in the upstream and should be available in the next release.
I think you can use a database view table to merge data from 2 schemas, and then use Zend Framework to fetch data from that table.

Categories