In my project I have the following DQL extension
namespace Freedom\Doctrine\ORM\AST\Functions;
use Doctrine\ORM\Query\AST\Functions\FunctionNode;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\Parser;
use Doctrine\ORM\Query\SqlWalker;
/**
* MatchAgainstFunction ::=
* "MATCH" "(" StateFieldPathExpression {"," StateFieldPathExpression}* ")" "AGAINST" "("
* StringPrimary ["BOOLEAN"] ["EXPAND"] ")"
*/
class MatchAgainstFunction extends FunctionNode
{
/** #var array list of \Doctrine\ORM\Query\AST\PathExpression */
protected $pathExp = null;
/** #var string */
protected $against = null;
/** #var boolean */
protected $booleanMode = false;
/** #var boolean */
protected $queryExpansion = false;
public function parse(Parser $parser)
{
// match
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
// first Path Expression is mandatory
$this->pathExp = array();
$this->pathExp[] = $parser->StateFieldPathExpression();
// Subsequent Path Expressions are optional
$lexer = $parser->getLexer();
while ($lexer->isNextToken(Lexer::T_COMMA)) {
$parser->match(Lexer::T_COMMA);
$this->pathExp[] = $parser->StateFieldPathExpression();
}
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
// against
if (strtolower($lexer->lookahead['value']) !== 'against') {
$parser->syntaxError('against');
}
$parser->match(Lexer::T_IDENTIFIER);
$parser->match(Lexer::T_OPEN_PARENTHESIS);
$this->against = $parser->StringPrimary();
if (strtolower($lexer->lookahead['value']) === 'boolean') {
$parser->match(Lexer::T_IDENTIFIER);
$this->booleanMode = true;
}
if (strtolower($lexer->lookahead['value']) === 'expand') {
$parser->match(Lexer::T_IDENTIFIER);
$this->queryExpansion = true;
}
$parser->match(Lexer::T_CLOSE_PARENTHESIS);
}
public function getSql(SqlWalker $walker)
{
$fields = array();
foreach ($this->pathExp as $pathExp) {
$fields[] = $pathExp->dispatch($walker);
}
$against = $walker->walkStringPrimary($this->against)
. ($this->booleanMode ? ' IN BOOLEAN MODE' : '')
. ($this->queryExpansion ? ' WITH QUERY EXPANSION' : '');
return sprintf('MATCH (%s) AGAINST (%s)', implode(', ', $fields), $against);
}
}
and in my DQL I have
$builder->andWhere('MATCH (t.title) AGAINST (:title)')
->setParameter('title', $param);
I am getting the error
[Syntax Error] line 0, col 204: Error: Expected =, <, <=, <>, >, >=, !=, got 'ORDER'
I have an orderBy after the andWhere in my DQL.
Does anyone know why Doctrine is looking for a comparison operator?
I have figured it out. I changed my DQL to
$builder->andWhere('MATCH (t.title) AGAINST (:title BOOLEAN) > 0')
->setParameter('title', $param);
and it seems to be working now.
Related
I have Post and Tag entities with many-to-many relationship. In Post create and edit form there is a textbox where I can enter tags separated by comma relevant to that post. For example, when I enter tag1, tag2, tag3 for post with title 'Post1', the form will create post and tag entities and add these tags to tags list of that post.I use data transformer to create tag entities.
class Post{
/**
* #ORM\ManyToMany(targetEntity="Tag", mappedBy="posts",cascade={"all"})
*/
protected $tags;
public function __construct() {
$this->tags = new ArrayCollection();
}
/**
* #return ArrayCollection
*/
public function getTags()
{
return $this->tags;
}
/**
* #param Tag $tag
*/
public function addTag(Tag $tag)
{
$tag->addPost($this);
$this->tags->add($tag);
}
/**
* #param Tag $tag
*/
public function removeTag(Tag $tag)
{
$this->tags->removeElement($tag);
}
}
PostType
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('title', TextType::class, array('label' => 'Title'))
->add('tags', TextType::class, array('label' => 'Tags'))
;
$builder->get('tags')
->addModelTransformer(new TagViewTransformer($this->manager));
}
TagViewTransformer
class TagViewTransformer implements DataTransformerInterface
{
public function transform($value)
{
/...
}
public function reverseTransform($value)
{
$tags = array();
if ( $value )
{
if( strpos($value, ',') !== false )
{
$list = array_unique(explode(",", $value));
}
else
{
$list = array(trim($value));
}
foreach ( $list AS $tagName )
{
$tag = $this->em
->getRepository('CoreBundle:Tag')
->findOneBy(array('name' => trim($tagName)));
if( !$tag )
{
$tag = new Tag();
$tag->setName(trim($tagName));
$this->em->persist($tag);
}
$tags[] = $tag;
}
}
return $tags;
}
}
This works fine when I try to create Post, all tags are transformed to entities and are added to Post's tags list. but when I try to edit, I start having problems
public function editAction(Request $request, Post $post)
{
$deleteForm = $this->createDeleteForm($post);
$editForm = $this->createForm(PostType::class, $post);
$editForm->handleRequest($request);
$originalTags = $post->getTags();
if ($editForm->isSubmitted() && $editForm->isValid()) {
$em = $this->getDoctrine()->getManager();
$newTags = $editForm->get('tags')->getData();
foreach ($originalTags as $currentTag) {
if (!in_array($currentTag, $newTags)) {
$post->removeTag($currentTag);
}
}
$em->persist($post);
$em->flush();
return $this->redirectToRoute('post_show', array('id' => $post->getId()));
}
return $this->render('AppBundle:Post:edit.html.twig', array(
'entity' => $post,
'form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
Let's say Post has tags: tag1, tag2, tag3, but I want to remove tag3 and add tag4. So I will change tags textbox to tag1, tag2, tag4. However when I submit form, I get tag1, tag2, tag3, tag4. So tag3 is not removed from Post's tag list.
What is wrong with the editAction code?
try with this
public function editAction(Request $request, Post $post)
{
$deleteForm = $this->createDeleteForm($post);
$editForm = $this->createForm(PostType::class, $post);
$editForm->handleRequest($request);
if ($editForm->isSubmitted() && $editForm->isValid()) {
$em = $this->getDoctrine()->getManager();
$em->persist($post);
$em->flush();
return $this->redirectToRoute('post_show', array('id' => $post->getId()));
}
return $this->render('AppBundle:Post:edit.html.twig', array(
'entity' => $post,
'form' => $editForm->createView(),
'delete_form' => $deleteForm->createView(),
));
}
Use Orphan removal to do this :
class Post
{
/**
* #ORM\ManyToMany(targetEntity="Tag", mappedBy="posts", cascade={"all"}, orphanRemoval=true)
*/
protected $tags;
/* Rest of your class */
}
Do some tests, maybe cascade all is not necessary here.
I have a problem with a zend2 form. I made an entity which gets some data from the database and joins some tables...
here is the entity:
class Campaigns
{
/**
* #ORM\Id
* #ORM\GeneratedValue(strategy="AUTO")
* #ORM\Column(type="integer")
*/
protected $id;
/**
*
* #ORM\Column(name="campaign_name", type="string")
*
*/
protected $campaigns;
/**
* #var mixed
*
* #ORM\ManyToMany(targetEntity="Application\Entity\Countries", cascade={"persist"}, orphanRemoval=false)
* #ORM\JoinTable(name="campaigns_countries",
* joinColumns={#ORM\JoinColumn(name="campaign_id", referencedColumnName="id", onDelete="CASCADE")},
* inverseJoinColumns={#ORM\JoinColumn(name="country_id", referencedColumnName="id", onDelete="CASCADE")}
* )
*/
protected $countries;
Below this code are the getters and setters, a construct function, an add and an remove function.
Here they are:
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
return $this;
}
public function getCampaigns()
{
return $this->campaigns;
}
public function setCampaigns($campaigns)
{
$this->campaigns = $campaigns;
return $this;
}
public function addCampaigns($campaigns = null)
{
foreach ($campaigns as $c) {
if (!$this->campaigns->contains($c)) {
$this->campaigns->add($c);
}
}
}
public function removeCampaigns($campaigns)
{
foreach ($campaigns as $c) {
if ($this->campaigns->contains($c)) {
$this->campaigns->removeElement($c);
}
}
}
public function getCountries()
{
return $this->countries;
}
public function setCountries($countries)
{
$this->countries = $countries;
return $this;
}
public function addCountries($countries = null)
{
foreach ($countries as $c) {
if (!$this->countries->contains($c)) {
$this->countries->add($c);
}
}
}
public function removeCountries($countries)
{
foreach ($countries as $c) {
if ($this->countries->contains($c)) {
$this->countries->removeElement($c);
}
}
} //construct for countries
public function __construct()
{
$this->setCountries(new ArrayCollection());
}
My problem is with the protected $countries. If i add in the form the property value, it gives me the "countries" property not found in entity.
If I do not add it, and instead use __toString() function, it gives me an error saying that it could not convert countries to string...in the __toString() function I added the following code:
public function __toString()
{
return $this->countries;
}
Thank you for all your help!
AE
You say you want a string containing all related countries. The following code demonstrates how you could achieve this:
$campaignCountryNames = array();
$campaignCountries = $campaign->getCountries();
foreach ($campaignCountries as $country) {
// I assume your Country entity has a name property
$campaignCountryNames[] = $country->getName();
}
echo implode(', ', $campaignCountryNames);
i have two entities, entry and comments.
comments:
/**
* #Entity(repositoryClass="\Entities\Blog\CommentRepository")
* #Table(name="blog_comment")
* #HasLifecycleCallbacks
*/
class Comment extends \Entities\AbstractEntity
{
/**
* #Id #Column(name="id", type="integer")
* #GeneratedValue(strategy="AUTO")
*/
protected $id;
/**
* #ManyToOne(targetEntity="Entry", inversedBy="comments")
* #JoinColumn(name="entry_id", referencedColumnName="id")
*/
protected $entry;
/** #Column(name="approved", type="string", length=255) */
protected $approved;
/** #Column(name="title", type="string", length=255) */
protected $title;
/** #Column(name="content", type="text") */
protected $content;
/** #Column(name="pub_date", type="datetime") */
protected $pub_date;
/** #Column(type="datetime") */
private $created_at;
/** #Column(type="datetime") */
private $updated_at;
/** #PreUpdate */
public function updated()
{
$this->updated_at = new \DateTime("now");
}
public function __construct()
{
$this->created_at = $this->updated_at = new \DateTime("now");
}
}
class CommentRepository extends \Entities\PaginatedRepository
{
protected $_entityClassName = 'Entities\Blog\Comment';
}
and entry:
<?php
namespace Entities\Blog;
/**
* #Entity(repositoryClass="\Entities\Blog\EntryRepository")
* #Table(name="blog_entry")
* #HasLifecycleCallbacks
*/
class Entry extends \Entities\AbstractEntity
{
/**
* #Id #Column(name="id", type="integer")
* #GeneratedValue(strategy="AUTO")
*/
protected $id;
/** #Column(name="permalink", type="string", length=255) */
protected $permalink;
/** #Column(name="title", type="string", length=255) */
protected $title;
/** #Column(name="pub_date", type="datetime") */
protected $pub_date;
/** #Column(name="content", type="text") */
protected $content;
/** #OneToMany(targetEntity="Comment", mappedBy="entry") */
protected $comments;
public function getUrl()
{
$root_url = "/blog";
$archive_url = $this->getArchiveUrl();
$permalink_url = $this->getPermalinkUrl();
$url = "$root_url/$archive_url/$permalink_url";
return $url;
}
public function getArchiveUrl()
{
return $this->pub_date->format('m/d/Y');
}
public function getPermalinkUrl()
{
return ($this->permalink ? $this->permalink : $this->id);
}
public function getBreadcrumbs($url = 'UNINITIALIZED', $result = array())
{
$url = $url == 'UNINITIALIZED' ? $this->getUrl() : $url;
$url = $url ? $url : '/';
preg_match('#^(.*)/([^/]{1,})$#',$url,$matches);
$crumbs = isset($matches[1]) ? $matches[1] : '';
$current = isset($matches[2]) ? $matches[2] : '';
$title = ($this->getPermalinkUrl() == $current ? $this->title :
($current == 'blog' ? 'Blog' :
($current == '' ? 'Home' : $current)
)
);
// generate the breadcrumb for this page
$crumb = array(
'url' => $url,
'title' => $title,
);
// prepend it to the list of crumbs
array_unshift($result, $crumb);
// if this page has a parent
if ($url != '/') {
$url = $crumbs;
// add the parent's breadcrumb to the result
return $this->getBreadcrumbs($url, $result);
}
return $result;
}
/** #Column(type="datetime") */
private $created_at;
/** #Column(type="datetime") */
private $updated_at;
/** #PreUpdate */
public function updated()
{
$this->updated_at = new \DateTime("now");
}
public function __construct()
{
$this->comments = new \Doctrine\Common\Collections\ArrayCollection();
$this->created_at = $this->updated_at = new \DateTime("now");
}
}
class EntryRepository extends \Entities\PaginatedRepository
{
protected $_entityClassName = 'Entities\Blog\Entry';
}
how do i add a comment row? on phpmyadmin, it has a drop down of all the entry (blog entry) which you can select all which entry to use to add a row. but how do i do this with doctrine2?
i have tried:
$getEntry = $this->_entryRepo->findOneBy(array('id' => $entryId));
$getEntry = $this->_em->getReference('\Entities\Blog\Entry', $entryId);
$getDiscovery->entry->add($getEntry);
$this->_doctrine->flush();
but its adding null to entry_id
also tried:
$entity = array('entry_id' => $userid, 'title' => 'new title');
$obj = new \Entities\Blog\Comments;
$obj->setData($entity);
//also this
$obj->entry_id=2;
$this->_doctrine->persist($obj);
$this->_doctrine->flush();
$this->_doctrine->clear();
this adds everything but not the entry_id, this is always null
Doctrine documentation have a good topic on it. Looks like you have your changes on inverse side of relationship, which is not synchronized to DB.
Try replacing $obj->entry_id=2; with $obj->entry=$entity;, if it will help that's definitely mean that you are modifying the wrong association side.
I want to know how to test the models in zend framework, but it give me a error when I run the test, the code is the following:
this is the model I want to test:
<?php
class Application_Model_User extends Custom_Model_Base {
protected $_table = 'user';
protected $_primary = array('id');
protected $_primary_ai = 'id';
protected $_data = array();
protected $_data_changed = array();
protected $_readonly = array('id');
static
protected $_columns = array(
'id',
'login',
'password_hash',
'name',
'surname',
'gender',
'street',
'postal_code',
'city',
'mobile',
'homephone',
'email',
'is_active');
public function __construct() {
parent::__construct();
}
static function create(array $data) {
return parent::_create(
$_table,
get_class(),
$data,
self::$_columns,
true
);
}
static function load($id) {
return self::_selectAndBind(
get_class(),
self::getDefaultAdapter()
->select()
->from($_table)
->where('id = ?', array($id)),
true);
}
static function find($name, $order=null, $limit=null, $offset=null) {
return self::_selectAndBind(
get_class(),
self::getDefaultAdapter()
->select()
->from($_table)
->where('name = ?', array($name))
->order($order)
->limit($limit, $offset)
);
}
}
it extends a base class, which is :
<?
abstract class Custom_Model_Base
{
/** #var Zend_Db_Adapter_Abstract */
static protected $_db_default = null;
/** #var Zend_Db_Adapter_Abstract */
protected $_db = null;
protected $_table = '';
protected $_primary = array();
/** $var string indicates which column from pk using auto increment function, set to null if none column is using auto incrementation */
protected $_primary_ai = null;
protected $_data = array();
protected $_data_changed = array();
protected $_readonly = array();
/**
* #param Zend_Db_Adapter_Abstract $adapter overrides global (static) adapter used for all models
*/
protected function __construct($adapter=null) {
if ($adapter !== null) {
if ($adapter instanceof Zend_Db_Adapter_Abstract)
{
$this->_db = $adapter;
return;
}
$this->_db = &self::$_db_default;
}
}
/**
* #param $default_adapter allows to set default adapter for whole model layer based on that class
*/
static public function init($default_adapter = null)
{
if (self::$_db_default === null)
{
if (!is_null($default_adapter))
{
if (!$default_adapter instanceof Zend_Db_Adapter_Abstract)
{
throw new Exception('Provided adapter does not extend Zend_Db_Adapter_Abstract');
}
self::$_db_default = $default_adapter;
}
else if (Zend_Registry::isRegistered('db'))
{
self::$_db_default = Zend_Registry::get('db');
}
else
{
throw new Exception('No default adapter provided for the model layer');
}
}
}
/**
* #return Zend_Db_Adapter_Abstract default database adapter
*/
static public function getDefaultAdapter()
{
return self::$_db_default;
}
/**
* Saves changed columns from the model object
* #return bool success - true / failure - false
*/
public function save()
{
$to_update = array();
foreach(array_keys($this->_data_changed) as $col)
{
$to_update[$col] = $this->_data[$col];
}
if (count($to_update))
{
// create where clause
$where = array();
foreach($this->_primary as $pk)
{
$where = array($pk.' = ?' => $this->_data[$pk]);
}
return ($this->_db->update($this->_table, $to_update, $where) != 0);
}
else
{
return true;
}
}
public function __set($n, $v)
{
if (!isset($this->_data[$n]))
{
throw new Exception('Column \''.$n.'\' doesn\'t exists');
}
else if (in_array($n, $this->_readonly))
{
throw new Exception('Column \''.$n.'\' is set as read-only');
}
if ($this->_data[$n] != $v)
{
$this->_data_changed[$n] = 1;
$this->_data[$n] = $v;
}
}
public function __get($v)
{
if (!isset($this->_data[$n]))
{
throw new Exception('Column \''.$n.'\' doesn\'t exists');
}
return $this->_data[$n];
}
}
my test code is :
<?php
require_once(APPLICATION_PATH.'/models/CustomModelBase.php');
class Model_User2Test
extends PHPUnit_Framework_TestCase
{
protected $_model;
public function setUp() {
parent::setUp();
$this->_model = new Application_Model_User2();
//$foo = $this->getMock();
}
public function testCanDoTest() {
$this->assertInstanceOf('Application_Model_User2', $this->_model);
//$this->assertType('Application_Model_User2',new Application_Model_User2());
}
public function testCanFind() {
$this->assertTrue(true);
$this->_model->init();
$this->assertNotNull($this->_model->find('admin'));
}
}
when I run the test,it give me error:
1) Model_User2Test::testCanFind
Undefined variable: _table
application\models\User2.php:57
tests\application\models\User2Test.php:27
why the _table is not defined? actually it is defined when I create the object? how could I fix it?
You declare _$table as protected:
protected $_table = 'user';
So you can't access it as you are doing through an instantion of the class. Only a class that inherits can do that. You need to declare it public, or use a getter/setter style access.
Edit:
static function load($id) {
return self::_selectAndBind(
get_class(),
self::getDefaultAdapter()
->select()
// $this->_table not $table
->from($_table)
->where('id = ?', array($id)),
true);
}
In your class, you're using $_table and not $this->_table. This is the same in another location. Check over to make sure you're properly accessing class variables.
In your static method Application_Model_User::find(), you have this line in your query:
->from($_table)
But in this context, $_table is a local variable that never gets set. Sounds like you want to access $this->_table instead.
[ As a side note: since you have defined find() as a static method, you can run into issues when trying to reference $this during a static call. Of course, in your test, you do seem to call the find() on an instance, so you should be fine in this respect. Do you really need find() to be a static method?]
How would I test my mappers in Zend_Db?
Each of my model will have 3 classes:
The Model
The Mapper
The DbTable
Here is my Unit Test:
<?php
// Call Model_BugTest::main() if this source file is executed directly.
if (!defined("PHPUnit_MAIN_METHOD")) {
define("PHPUnit_MAIN_METHOD", "Model_ArtistTest::main");
}
require_once dirname(__FILE__) . '/../../TestHelper.php';
/** Model_Artist */
require_once 'Artist.php';
/**
* Test class for Model_Artist.
*
* #group Models
*/
class Model_ArtistTest extends PHPUnit_Framework_TestCase
{
/**
* Runs the test methods of this class.
*
* #return void
*/
public static function main()
{
$suite = new PHPUnit_Framework_TestSuite("Model_ArtistTest");
$result = PHPUnit_TextUI_TestRunner::run($suite);
}
/**
* Sets up the fixture, for example, open a network connection.
* This method is called before a test is executed.
*
* #return void
*/
public function setUp()
{
$this->model = new Ly_Model_Artist();
}
/**
* Tears down the fixture, for example, close a network connection.
* This method is called after a test is executed.
*
* #return void
*/
public function tearDown()
{
}
public function testCanDoTest()
{
$this->assertTrue(true);
}
public function testCanFindArtist()
{
$artist = "Rage Against the Machine";
$result = $this->model->findbyalpha($artist);
var_dump($result);
}
}
I am using Matthew's TestHelper: http://github.com/weierophinney/bugapp/blob/master/tests/TestHelper.php
The error I get is this:
c:\xampp\htdocs\ly\tests>phpunit --configuration phpunit.xml
PHPUnit 3.4.10 by Sebastian Bergmann.
.
Fatal error: Class 'Ly_Model_ArtistMapper' not found in C:\xampp\htdocs\ly\appli
cation\models\Artist.php on line 72
Seems like the Mapper is not being read. Can anyone show me how to do this kind of testing? I am new to UnitTesting and I am just starting to learn it.
This is my Artist Model
<?php
/**
* Artist Model
*/
class Ly_Model_Artist
{
protected $_id; //a field
protected $_name; //a field
protected $_mapper;
public function __construct(array $options = null)
{
if (is_array($options)) {
$this->setOptions($options);
}
}
public function __set($name, $value)
{
$pieces = explode('_', $name);
foreach($pieces AS $key => $row) {
$pieces[$key] = ucfirst($row);
}
$name = implode('',$pieces);
$method = 'get' . $name;
if (('mapper' == $name) || !method_exists($this, $method)) {
throw new Exception('Invalid group property');
}
$this->$method($value);
}
public function __get($name)
{
$pieces = explode('_', $name);
foreach($pieces AS $key => $row) {
$pieces[$key] = ucfirst($row);
}
$name = implode('',$pieces);
$method = 'get' . $name;
if (('mapper' == $name) || !method_exists($this, $method)) {
throw new Exception('Invalid group property');
}
return $this->$method();
}
public function setOptions(array $options)
{
$methods = get_class_methods($this);
foreach ($options as $key => $value) {
$method = 'set' . ucfirst($key);
if (in_array($method, $methods)) {
$this->$method($value);
}
}
return $this;
}
public function setMapper($mapper)
{
$this->_mapper = $mapper;
return $this;
}
public function getMapper()
{
if (null === $this->_mapper) {
$this->setMapper(new Ly_Model_ArtistMapper());
}
return $this->_mapper;
}
public function setId($id)
{
$this->_id = (int) $id;
return $this;
}
public function getId()
{
return $this->_id;
}
public function setName($text)
{
$this->_name = (string) $text;
return $this;
}
public function getName()
{
return $this->_name;
}
public function find($id)
{
$this->getMapper()->find($id, $this);
return $this;
}
public function findbyalpha($keyword)
{
return $this->getMapper()->findbyalpha($keyword);
}
}
This is the Artist Mapper:
<?php
/**
* Artist Model Mapper
*/
class Ly_Model_ArtistMapper
{
protected $_dbTable;
public function setDbTable($dbTable)
{
if (is_string($dbTable)) {
$dbTable = new $dbTable();
}
if (!$dbTable instanceof Zend_Db_Table_Abstract) {
throw new Exception('Invalid table data gateway provided');
}
$this->_dbTable = $dbTable;
return $this;
}
public function getDbTable()
{
if (null === $this->_dbTable) {
$this->setDbTable('Ly_Model_DbTable_Artist');
}
return $this->_dbTable->getAdapter();
}
public function find($id, Ly_Model_Artist $artist)
{
if(!isset($id) OR empty($id)) {
throw new Exception ('Could not find id.');
}
$result = $this->getDbTable()->find($id);
if (0 == count($result)) {
return;
}
$row = $result->current();
$artist->setId($row->id)
->setName($row->name);
}
public function findbyalpha($keyword)
{
if(!isset($keyword) OR empty($keyword)) {
throw new Exception ('Could not find keyword.');
}
$keyword = $this->getDbTable()->quote($keyword.'%');
//$sql = $this->getDbTable()->select()->where('twitter_id = ?',$twitter_id)->order('weight');
$sql = "SELECT
DISTINCT
a.name
FROM artist a
WHERE a.name LIKE ".$keyword."
ORDER BY a.name ASC
";
//Zend_Debug::dump($sql);
$result = $this->getDbTable()->fetchAll($sql);
return $result;
}
}
And the Db_Table just looks like this:
<?php
class Ly_Model_DbTable_Artist extends Zend_Db_Table_Abstract
{
protected $_name = 'artist';
}
Change the mapper to use the Inversion of Control pattern (insert the DB Table Object into the constructor (at least optionally) that way you can disconnect it and pass in a mock/stub object.
You should test your models (which call your mapper). That way, you will know if something is wrong with your mappers.
Have you tried in your Artists model setting the mapper method like
public function setMapper(Ly_Model_ArtistMapper $mapper)
{
...
}
Unit tests are meant to test a small amount of work, i.e. a method. Everything that the method depends on should be mocked/stubbed (success/failure) out as that will be tested else where in another unit test.