i'm new to zend framework, in this simple function i want to get a single 'post' and then i want to find all the comments in the related table
public function getPost($idPost)
{
$db= Zend_Registry::get('db');
$select=$db->select()
->from($this->_name, '*')
->where("idPost= ".$db->quote($idPost, 'INTEGER'));
$stmt=$select->query();
$rowset=$stmt->fetchAll();
$post=$rowset->current();
//ora devo aggiungerci i commenti che questo post ha ricevuto
$comm=$post->findDependentRowset('commenti');
$ris=array($post, $comm);
return $ris;
}
in my index controller i i simply call this function, but i get this error:
Call to a member function current() on a non-object in C:\xampp\htdocs\...
where's the mistake?
I think you have a few misconceptions about how you're using Zend_Db.
1. You're not using the ORM, just the PDO wrapper
Which means, your queries won't return Zend rowsets and rows and therefore you can't use the methods of you can use on those.
2. The default fetch mode
The default fetch mode of the Zend_Db_Statement fetchAll() method is array, if you want it to return an object (stdClass), change the fetch mode before fetching the data:
$stmt->setFetchMode(Zend_Db::FETCH_OBJ);
3. Using fetchAll() when you actually want one row
If you just want one row, then don't fetch a whole table! With Zend_Db_Statement, use for example:
$row = $stmt->fetch();
or
$rowObj = $stmt->fetchObject();
... again, that's not a zend row object, just a stdClass instance, but you can do:
$rowObj->some_field;
on it.
On the other hand, if this is a method in your Post model, it should look something like:
public function getPost($idPost)
{
return $this->getRow($idPost);
}
This will return the post, then, if you've setup the table relationships correctly, you can also query for the dependent data or just get all comments with that id separately.
The problem is that unless you define a table class as was previously mentioned you can't uuse the dependent or parent rowsets.
To make your current function work would be best done with two functions, and keep it simple:
public function getPost($idPost)
{
$db= new Zend_Db_Table($this->_name);
$select=$db->select()
->where("idPost= ?", $idPost);
/*Fetch just the row you want, or use fetchAll() if you need to match return types*/
$row = $db->fetchRow($select);
return $row;
}
public function getComments($table='comments', $id) {
$db = new Zend_Db_table($table);
$select = $db->select()->where('post_id = ?', $id)->order('date ASC');
$rowset = $db->fetchAll($select);
return $rowset/* or you could return an array ->$rowset->toArray() */
}
Zend_Db_Table is going to attempt to use the current database adapter, so all you need to do is pass in the tablename.
One more note: you don't need to use any of the quote() function when using select() it's taken care of.
But it is really important, that if you are going to use Zend_Db, you need to learn about "Defining table classes". At least enough to use them in your own classes.
I hope this helps!
To get a rowset and dependent rowset you have to use Zend_Db_Table.
You only use the Zend_Db_Adapter with Zend_Db_Select.
Read from here.
So you have to define a class which extends from Zend_Db_Table_Abstract.
Example:
class Bugs extends Zend_Db_Table_Abstract
{
protected $_name = 'bugs';
protected $_primary = 'bug_id';
}
To get the Zend_Db_Table_Rowset object use:
$bugs = new Bugs();
$rowset = $bugs->fetchAll("bug_status = 'NEW'");
To find dependent rowsets you have to define the relation in your table class. Look here how to define relationships.
Related
There is some basic understanding/theory here that I am missing.I don't understand the difference between these function calls:
$distributors = $store->distributors();
$distributors = $store->distributors;
$distributors = $store->distributors()->get();
$distributors = $store->distributors->get();
What I am trying to accomplis here is to get a list of the distributors for a store (a many to many relationship), and they get each distributors list of beers into one giant list.
foreach ($distributors as $distributor)
{
$available_beers = array_merge($distributor->beers(), $available_beers);
}
I don't know if that is the best way to do this and I can't get it to work. Similar to the first list of methods, I don't know if I need ->$beers or ->$beers()
Update
Thanks to everyone who answered! This will be a good reference for me going forward. My biggest lesson was the difference between getting a collection back, vs getting the query builder/relationship object back. For future reference to those who find this question, here is what I set up in my controller:
$store = $this->store->find($id)->first();
$distributors = $store->distributors;
$beers = [];
foreach ($distributors as $distributor){
$beers = array_merge($distributor->beers->lists('name', 'id'), $beers);
}
Short answer
$model->relation() returns the relationship object
$model->relation returns the result of the relationship
Long answer
$model->relation() can be explained pretty simple. You're calling the actual function you defined your relation with. Yours for distributor probably looks somewhat like this:
public function distributors(){
return $this->hasMany('Distributor');
}
So when calling $store->distributors() you just get the return value of $this->hasMany('Distributor') which is an instance of Illuminate\Database\Eloquent\Relations\HasMany
When do you use it?
You usually would call the relationship function if you want to further specify the query before you run it. For example add a where statement:
$distributors = $store->distributors()->where('priority', '>', 4)->get();
Of course you can also just do this: $store->distributors()->get() but that has the same result as $store->distributors.
Which brings me to the explanation of the dynamic relationship property.
Laravel does some things under the hood to allow you to directly access the results of a relationship as property. Like: $model->relation.
Here's what happens in Illuminate\Database\Eloquent\Model
1) The properties don't actually exist. So if you access $store->distributors the call will be proxied to __get()
2) This method then calls getAttribute with the property name getAttribute('distributors')
public function __get($key)
{
return $this->getAttribute($key);
}
3) In getAttribute it checks if the relationship is already loaded (exists in relations). If not and if a relationship method exists it will load the relation (getRelationshipFromMethod)
public function getAttribute($key)
{
// code omitted for brevity
if (array_key_exists($key, $this->relations))
{
return $this->relations[$key];
}
$camelKey = camel_case($key);
if (method_exists($this, $camelKey))
{
return $this->getRelationshipFromMethod($key, $camelKey);
}
}
4) In the end Laravel calls getResults() on the relation which then results in a get() on the query builder instance. (And that gives the same result as $model->relation()->get().
The direct answer to your question:
$store->distributors() will return the actual relationship object (\Illuminate\Database\Eloquent\Relations\BelongsToMany).
$store->distributors will be a collection containing the results of the relationship query (\Illuminate\Database\Eloquent\Collection).
$store->distributors()->get() will be a collection containing the results of the relationship query (\Illuminate\Database\Eloquent\Collection).
$store->distributors->get() should return an error since you're calling get() on a Collection object and the first parameter is not optional. If not an error, it should at least return null.
More information:
Given the following model:
class Store extends Eloquent {
public function distributors() {
return $this->belongsToMany('Distributor');
}
}
Calling the relationship method ($store->distributors()) will return to you the relationship (\Illuminate\Database\Eloquent\Relations\BelongsToMany) object. This is basically a query object which you can continue to modify, but you still need to call some type of method to get the results (e.g. get(), first(), etc).
However, accessing the relationship attribute ($store->distributors) will return to you a collection (\Illuminate\Database\Eloquent\Collection) object containing the results from executing the relationship query.
By default, the relationship attribute is created and assigned a value the first time it is accessed (known as "lazy loading"). So, the first time you access $store->distributors, behind the scenes it is executing the relationship query, storing the results in the $store->distributors attribute, and then returning those results. However, it only does this once. The next time you access $store->distributors, the attribute already contains the data, so that is what you are accessing.
To illustrate this:
// the following two statements will run the query twice
$r1 = $store->distributors()->get();
$r2 = $store->distributors()->get();
// the following two statements will run the query once.
// the first statement runs the query, populates $store->distributors, and assigns the variable
// the second statement just accesses the data now stored in $store->distributors
$r3 = $store->distributors;
$r4 = $store->distributors;
// at the end, $r1 == $r2 == $r3 == $r4
Relationships can also be "eager" loaded, using the with() method on the query. This is done to alleviate all of the extra queries that may be needed for lazy loading (known as the n+1 problem). You can read more about that here.
When you work with relationships with Eloquent the property is a collection (Illuminate\Database\Eloquent\Collection) of your relation white the method is a start of a new query.
Say your model looks like this:
class User extends Eloquent {
public function roles()
{
return $this->belongsToMany('Role');
}
}
If you try to access $user->roles, Eloquent will run the query and fetch all roles related to that user thanks to magic methods and returns an instance of Illuminate\Database\Eloquent\Collection. That class has a method called get, that's why $user->roles->get() works for you.
If you try to access the method, $user->roles(), you will instead get a query builder object so you can fine tune your query.
$user->roles()->whereIn('role_id', [1, 3, 4])->get();
That would only return roles where role_id is 1, 3 or 4.
So, the property returns a complete query and it results (Illuminate\Database\Eloquent\Collection) while the method lets you customize your query.
$distributors = $store->distributors();
Result of a method (function)
$distributors = $store->distributors;
Value of property (variable)
$distributors = $store->distributors()->get();
Take the first one, where it's the result of a method, if the method returns an object, this is a method in that object that was returned.
$distributors = $store->distributors->get();
If the property is an object, then it's calling a method in that property that's an object.
Re ->$beers vs ->$beers() that's a dynamic name of a property/method depending on what you're for. Just make a really rough guess at what you're doing, in your class you're going to have
$this->beers = array('bud','miller','sam');
and in your code using the $store object, you're actually going to go something like
$drink_type = 'beers';
$drink_list = $store->$drink_type;
And that will return $this->beers from $store, the same as writing $store->beers;
Imagine that the store class looks like this:
<?php
class Store {
public $distributors;
function __construct($distributors = array()) {
$this->distributors = $distributors;
}
public function distributors() {
return $this->distributors;
}
}
So the difference is:
$store = new Store(array('some guy', 'some other guy'));
$guys = $store->distributors; # accesing the $distributors property
$more = $store->distributors(); # calling the distributors() method.
The main difference is:
$distributors = $store->distributors() return instance of the relationship object like Illuminate\Database\Eloquent\Relations\BelongsToMany. You can use other conditions such as where after call this.
$store->distributors return instance of the collection Illuminate/Database/Eloquent/Collection. Laravel call the magic method __get under the hood. It will return a result of query relationship.
Maybe this will be usefull.
Access to method:
$object->method();
Access to property:
$object->property;
I have the following example in which I tend to use a couple of classes, to create a simple web app.
The file hierarchy seems like this.
> cupid
- libs
- request
- router
- database
- view
- bootstrap.php
- index.php
The index.php just calls the bootstrap.php which in turn contains something like this:
// bootstrap.php
namespace cupid
use request, router, database, view;
spl_autoload_register(function($class){ /* autoload */ });
$request = new view;
$response = new response;
$router = new router;
$database = new database;
$router->get('/blog/{id}', function($id) use ($database, $view) {
$article = $database->select("SELECT blog, content FROM foo WHERE id = ?",[$id]);
$view->layout('blogPage', ['article'=>$article]);
});
As you can probably tell, my problem is this line:
$article = $database->select("SELECT blog, content FROM foo WHERE id = ?", [$id]);
Which I don't want to use, and instead try a " Domain Object Model " approach.
Now, given that I will add another folder called domain, with blog.php
> cupid
- domain
- Blog.php
- libs
...
And fill blog.php with properties mapping table rows, and getter and setters ..
namespace App\Domain;
class Blog {
private $id, $title, $content, $author;
public function getTitle(){
return $this->title;
}
public function setTitle($title){
$this->title = $title;
}
...
}
My question is: Assuming my understanding of DOM is so far correct, and that I have a CRUD/ORM class, or a PDO wrapper to query the database;
"How can I tie together, i.e. the blog model with the PDO wrapper to fetch a blog inside my bootstrap file?"..
As far as a Domain Object you basically already have written one, your blog object. To qualify as a domain model all a class must to is to provide a representation along with any of the functionality of a concept within your problem space.
The more interesting problem here and the one you appear to be struggling with is how to persist a domain model. Keeping with the tenet of the single responsibility principle your Blog class should deal with being a blog post and doing the things that a blog post can do, not storing one. For that you would introduce the concept of a repository of blog posts that would deal with storing and retrieving objects of this type. Below is a simple implementation of how this can be done.
class BlogRepository {
public function __construct(\cupid\database $db){
$this->db = $db;
}
public function findById($id){
$blogData = $this->db->select("select * from blog where id = ?", [$id]);
if ($blogData){
return $this->createBlogFromArray($blogData);
}
return null;
}
public function findAllByTag($tag){...}
public function save(Blog $blog) {...}
private function createBlogFromArray(array $array){
$blog = new Blog();
$blog->setId($blogData["id"]);
$blog->setTitle($blogData["title"]);
$blog->setContent($blogData["content"]);
$blog->setAuthor($blogData["author"]);
return $blog;
}
}
Then your controller should look something like this.
$router->get('/blog/{id}', function($id) use ($blogRepository, $view) {
$article = $blogRepository->findById($id);
if ($article) {
$view->layout('blogPage', ['article'=>$article]);
} else {
$view->setError("404");
}
});
To truly be SOLID the above class should be a database specific implementation of a BlogRepository interface to adhere to IoC. A factory should also probably be supplied to BlogRepository to actually create the blog objects from data retrieved from the store.
In my opinion one of the great benefits of doing this is you have a single place where you can implement and maintain all of your blog related interactions with the database.
Other Advantages to this method
Implementing caching for your domain objects would be trivial
Switching to a different data source (from flat files, blogger api, Document Database Server,PostgresSQL etc.) could be done easily.
You can alternatively use a type aware ORM for a more general solution to this same problem. Basically this Repository class is nothing more than a ORM for a single class.
The important thing here is that you are not talking directly to the database and leaving sql scattered throughout your code. This creates a maintenance nightmare and couples your code to the schema of your database.
Personally I always tend to stick the database operations in a database class which does all the heavy lifting of initialising the class, opening the connection etc. It also has generic query-wrappers to which I pass the SQL-statements which contains the normal placeholders for the bound variables, plus an array of the variables to be bound (or the variable number of parameters approach if thats suits you better). If you want to bind each param individually and not use the $stmt->execute(array()); You just pass in the types with the value in a data structure of your choosing, multi dim array, dictionary, JSON, whatever suits your needs and you find easy to work with.
The model class it self (Blog in your case) then subclasses the Database. Then you have a few choices to make. Do you want to use the constructor to create only new objects? Do you want it to only load based on IDs? Or a mix of both? Something like:
function __construct(id = null, title = null, ingress = null, body = null) {
if(id){
$row = $this->getRow("SELECT * FROM blog WHERE id = :id",id); // Get a single row from the result
$this->title = $row->title;
$this->ingress = $row->ingress;
$this->body = $row->body;
... etc
} else if(!empty(title,ingress,body)){
$this->title = title;
... etc
}
}
Maybe neither? You can skip the constructor and use the new(title, ingress, body), save() and a load(id) methods if thats your preference.
Of course, the query part can be generalised even further if you just configure some class members and let the Database-superclass do the query building based on what you send in or set as member-variables. For example:
class Database {
$columns = []; // Array for storing the column names, could also be a dictionary that also stores the values
$idcolumn = "id"; // Generic id column name typically used, can be overridden in subclass
...
// Function for loading the object in a generic way based on configured data
function load($id){
if(!$this->db) $this->connect(); // Make sure we are connected
$query = "SELECT "; // Init the query to base string
foreach($this->columns as $column){
if($query !== "SELECT ") $query .= ", "; // See if we need comma before column name
$query .= $column; // Add column name to query
}
$query .= " FROM " . $this->tablename . " WHERE " . $this->idcolumn . " = :" . $this->idcolumn . ";";
$arg = ["col"=>$this->idcolumn,"value"=>$id,"type"=>PDO::PARAM_INT];
$row = $this->getRow($query,[$arg]); // Do the query and get the row pass in the type of the variable along with the variable, in this case an integer based ID
foreach($row as $column => $value){
$this->$column = $value; // Assign the values from $row to $this
}
}
...
function getRow($query,$args){
$statement = $this->query($query,$args); // Use the main generic query to return the result as a PDOStatement
$result = $statement->fetch(); // Get the first row
return $result;
}
...
function query($query,$args){
...
$stmt = $this->db->prepare($query);
foreach($args as $arg){
$stmt->bindParam(":".$arg["col"],$arg["value"],$arg["type"]);
}
$stmt->execute();
return $stmt;
}
...
}
Now as you see the load($id), getrow($query,$args) and query($query,$args) is completely generic. ´getrow()´is just a wrapper on query() that gets the first row, you may want to have several different wrappers that to or interpret your statement result in different ways. You may also even want to add object specific wrappers to your models if they cannot be made generic. Now the model, in your case Blog could look like:
class Blog extends Database {
$title;
$ingress;
$body;
...
function __construct($id = null){
$this->columns = ["title","ingress","body","id",...];
$this->idcolumn = "articleid"; // override parent id name
...
if($id) $this->load($id);
}
...
}
Use it as so: $blog = new Blog(123); to load a specific blog, or $blog = new Blog(); $blog->title = "title"; ... $blog->save(); if you want a new.
"How can I tie together, i.e. the blog model with the PDO wrapper to fetch a blog inside my bootstrap file?"..
To tie the two together, you could use an object-relational mapper (ORM). ORM libraries are built just for glueing your PHP classes to database rows. There are a couple of ORM libraries for PHP around. Also, most ORMs have a built in database abstraction layer, which means that you can simply switch the database vendor without any hassle.
Considerations when using an ORM:
While introducing a ORM also introduces some bloat (and some learning), it may not be worthwhile investing the time for simply a single Blog object. Although, if your blog entries also have an author, one or multiple categories and/or associated files, an ORM may soon help you reading/writing the database. Judging from your posted code, an ORM will pay off when extending the application in the future.
Update: Example using Doctrine 2
You may have a look at the querying section of the official Doctrine documentation to see the different options you have for read access. Reconsider the example you gave:
// current implementation
$article = $database->select("SELECT blog, content FROM foo WHERE id = ?",[$id]);
// possible implementation using Doctrine
$article = $em->getRepository(Blog::class)->find($id);
However, ideally you define your own repository to separate your business logic from Doctrines API like the following example illustrates:
use Doctrine\ORM\EntityRepository;
interface BlogRepositoryInterface {
public function findById($id);
public function findByAuthor($author);
}
class BlogRepsitory implements BlogRepositoryInterface {
/** #var EntityRepository */
private $repo;
public function __construct(EntityRepository $repo) {
$this->repo = $repo;
}
public function findById($id) {
return $this->repo->find($id);
}
public function findByAuthor($author) {
return $this->repo->findBy(['author' => $author]);
}
}
I hope the example illustrates how easily you can separate your business domain models and logic from the underlying library and how powerful ORMs can come into play.
There is some basic understanding/theory here that I am missing.I don't understand the difference between these function calls:
$distributors = $store->distributors();
$distributors = $store->distributors;
$distributors = $store->distributors()->get();
$distributors = $store->distributors->get();
What I am trying to accomplis here is to get a list of the distributors for a store (a many to many relationship), and they get each distributors list of beers into one giant list.
foreach ($distributors as $distributor)
{
$available_beers = array_merge($distributor->beers(), $available_beers);
}
I don't know if that is the best way to do this and I can't get it to work. Similar to the first list of methods, I don't know if I need ->$beers or ->$beers()
Update
Thanks to everyone who answered! This will be a good reference for me going forward. My biggest lesson was the difference between getting a collection back, vs getting the query builder/relationship object back. For future reference to those who find this question, here is what I set up in my controller:
$store = $this->store->find($id)->first();
$distributors = $store->distributors;
$beers = [];
foreach ($distributors as $distributor){
$beers = array_merge($distributor->beers->lists('name', 'id'), $beers);
}
Short answer
$model->relation() returns the relationship object
$model->relation returns the result of the relationship
Long answer
$model->relation() can be explained pretty simple. You're calling the actual function you defined your relation with. Yours for distributor probably looks somewhat like this:
public function distributors(){
return $this->hasMany('Distributor');
}
So when calling $store->distributors() you just get the return value of $this->hasMany('Distributor') which is an instance of Illuminate\Database\Eloquent\Relations\HasMany
When do you use it?
You usually would call the relationship function if you want to further specify the query before you run it. For example add a where statement:
$distributors = $store->distributors()->where('priority', '>', 4)->get();
Of course you can also just do this: $store->distributors()->get() but that has the same result as $store->distributors.
Which brings me to the explanation of the dynamic relationship property.
Laravel does some things under the hood to allow you to directly access the results of a relationship as property. Like: $model->relation.
Here's what happens in Illuminate\Database\Eloquent\Model
1) The properties don't actually exist. So if you access $store->distributors the call will be proxied to __get()
2) This method then calls getAttribute with the property name getAttribute('distributors')
public function __get($key)
{
return $this->getAttribute($key);
}
3) In getAttribute it checks if the relationship is already loaded (exists in relations). If not and if a relationship method exists it will load the relation (getRelationshipFromMethod)
public function getAttribute($key)
{
// code omitted for brevity
if (array_key_exists($key, $this->relations))
{
return $this->relations[$key];
}
$camelKey = camel_case($key);
if (method_exists($this, $camelKey))
{
return $this->getRelationshipFromMethod($key, $camelKey);
}
}
4) In the end Laravel calls getResults() on the relation which then results in a get() on the query builder instance. (And that gives the same result as $model->relation()->get().
The direct answer to your question:
$store->distributors() will return the actual relationship object (\Illuminate\Database\Eloquent\Relations\BelongsToMany).
$store->distributors will be a collection containing the results of the relationship query (\Illuminate\Database\Eloquent\Collection).
$store->distributors()->get() will be a collection containing the results of the relationship query (\Illuminate\Database\Eloquent\Collection).
$store->distributors->get() should return an error since you're calling get() on a Collection object and the first parameter is not optional. If not an error, it should at least return null.
More information:
Given the following model:
class Store extends Eloquent {
public function distributors() {
return $this->belongsToMany('Distributor');
}
}
Calling the relationship method ($store->distributors()) will return to you the relationship (\Illuminate\Database\Eloquent\Relations\BelongsToMany) object. This is basically a query object which you can continue to modify, but you still need to call some type of method to get the results (e.g. get(), first(), etc).
However, accessing the relationship attribute ($store->distributors) will return to you a collection (\Illuminate\Database\Eloquent\Collection) object containing the results from executing the relationship query.
By default, the relationship attribute is created and assigned a value the first time it is accessed (known as "lazy loading"). So, the first time you access $store->distributors, behind the scenes it is executing the relationship query, storing the results in the $store->distributors attribute, and then returning those results. However, it only does this once. The next time you access $store->distributors, the attribute already contains the data, so that is what you are accessing.
To illustrate this:
// the following two statements will run the query twice
$r1 = $store->distributors()->get();
$r2 = $store->distributors()->get();
// the following two statements will run the query once.
// the first statement runs the query, populates $store->distributors, and assigns the variable
// the second statement just accesses the data now stored in $store->distributors
$r3 = $store->distributors;
$r4 = $store->distributors;
// at the end, $r1 == $r2 == $r3 == $r4
Relationships can also be "eager" loaded, using the with() method on the query. This is done to alleviate all of the extra queries that may be needed for lazy loading (known as the n+1 problem). You can read more about that here.
When you work with relationships with Eloquent the property is a collection (Illuminate\Database\Eloquent\Collection) of your relation white the method is a start of a new query.
Say your model looks like this:
class User extends Eloquent {
public function roles()
{
return $this->belongsToMany('Role');
}
}
If you try to access $user->roles, Eloquent will run the query and fetch all roles related to that user thanks to magic methods and returns an instance of Illuminate\Database\Eloquent\Collection. That class has a method called get, that's why $user->roles->get() works for you.
If you try to access the method, $user->roles(), you will instead get a query builder object so you can fine tune your query.
$user->roles()->whereIn('role_id', [1, 3, 4])->get();
That would only return roles where role_id is 1, 3 or 4.
So, the property returns a complete query and it results (Illuminate\Database\Eloquent\Collection) while the method lets you customize your query.
$distributors = $store->distributors();
Result of a method (function)
$distributors = $store->distributors;
Value of property (variable)
$distributors = $store->distributors()->get();
Take the first one, where it's the result of a method, if the method returns an object, this is a method in that object that was returned.
$distributors = $store->distributors->get();
If the property is an object, then it's calling a method in that property that's an object.
Re ->$beers vs ->$beers() that's a dynamic name of a property/method depending on what you're for. Just make a really rough guess at what you're doing, in your class you're going to have
$this->beers = array('bud','miller','sam');
and in your code using the $store object, you're actually going to go something like
$drink_type = 'beers';
$drink_list = $store->$drink_type;
And that will return $this->beers from $store, the same as writing $store->beers;
Imagine that the store class looks like this:
<?php
class Store {
public $distributors;
function __construct($distributors = array()) {
$this->distributors = $distributors;
}
public function distributors() {
return $this->distributors;
}
}
So the difference is:
$store = new Store(array('some guy', 'some other guy'));
$guys = $store->distributors; # accesing the $distributors property
$more = $store->distributors(); # calling the distributors() method.
The main difference is:
$distributors = $store->distributors() return instance of the relationship object like Illuminate\Database\Eloquent\Relations\BelongsToMany. You can use other conditions such as where after call this.
$store->distributors return instance of the collection Illuminate/Database/Eloquent/Collection. Laravel call the magic method __get under the hood. It will return a result of query relationship.
Maybe this will be usefull.
Access to method:
$object->method();
Access to property:
$object->property;
Is it possible to override values from Model->fetchAll() so it work globally. I have tried to override this in model, but does not work:
class Application_Model_DbTable_OdbcPush extends Zend_Db_Table_Abstract
{
public function __get(string $col)
{
$res = parent::__get($col);
if ($col == "lastrun") {
$res = ($res == "1912-12-12 00:00:00+07" ? NULL : $res);
}
return $res;
}
//...
}
In a controller:
$odbcModel = new Application_Model_DbTable_OdbcPush();
$rs = $odbcModel->fetchAll( $select );
I want to override value returned from fetchAll(), find() etc when col name is "lastrun";
The way you're going about this isn't going to work. __get is used to get data from protected or private properties and typically used in conjunction with getters.
For example, if you implemented __get() in your Application_Model_DbTable_OdbcPush class you could do something like:
$model = new Application_Model_DbTable_OdbcPush();
//echo out the _primary property (primary key of the table)
echo $model->primary;
and expect it to work. Because _primary exists as a property in Zend_Db_Table_Abstract.
To do what you want to do you'll need to do it after the result set has been returned (unless you want to rewrite the whole Zend Db component). Just run the result set through a foreach and change the value of lastrun to whatever you want.
I tried to find a place to override the Zend Db components to do what you want, but it would involve to many classes.
Remember that when using DbTable classes, they only interact with one table. You'll need to duplicate code for every table you want to effect or you'll need to extend a base class of some kind.
You always have the option to use straight Sql to frame whatever query you can come up with.
Good Luck!
Found the answer, for community i share here :D
http://framework.zend.com/manual/1.12/en/zend.db.table.row.html
So we have to overload Zend_Db_Table_Row and assign it to model/dbtable:
class Application_Model_DbTable_Row_OdbcPush extends Zend_Db_Table_Row_Abstract
{
// do some override here
}
class Application_Model_DbTable_OdbcPush extends Zend_Db_Table_Abstract
{
protected $_name = 'odbcpush';
protected $_primary = 'id';
private $_global = null;
protected $_rowClass = "Application_Model_DbTable_Row_OdbcPush";
// etc
}
Currently right now I'am using Zend_DB_Select, I would like to return the rows as objects so that I can use methods like save(), delete()
Function includes:
$table = self::instance();
$select = $table->getAdapter()->select();
$select->from('table1');
if($where != '')
{
$select->where($where);
}
$select->limit($count);
$select->order('id DESC');
$rs = $select->query()->fetchAll();
So right now Iam passing an array instead of object types.
If you want to operate on your resulting rows as objects (to call save(), delete() on them and so on) you need to use Zend_Db_Table_* and not just Zend_Db_* for your requests.
That way your resultset will be Zend_Db_Table_Row objects (instead of arrays or stdClass objects) and those objects have methods such as save() and delete() that you can call to manipulate and update individual rows in your code.
Start reading here:
http://framework.zend.com/manual/en/zend.db.table.html
Try this:
$rs = $select->query()->fetchAll(Zend_Db::FETCH_OBJ);
With Zend_Db::FETCH_OBJ, zend will return objects. It's all about fetch modes.