persist with many to many doctrine - doctrine-orm

I have a problem using Doctrine with many to many relation when I persist my data.
I have 2 entities :
- Bloc
- Job
I retrieve my ID's before the persist with getJobs() method.
$bloc = $form->getData();
// $bloc->getJobs() works I retrieve good IDs with foreach getId()
$em->persist($bloc);
$em->flush();
My method addJob :
/**
* Add jobs
*
* #param Job $jobs
* #return Bloc
*/
public function addJob(Job $jobs)
{
$this->jobs[] = $jobs;
return $this;
}
My form:
$bloc = $em->getRepository('Acme\\Entity\\Bloc')->find($id);
$form = $this->createForm(BlocType::class, $bloc);
$form->handleRequest();
if($form->isSubmitted()) {
$bloc = $form->getData();
$em->persist($bloc);
$em->flush();
$this->addFlashMessage('edit', "Update message");
}
But the persist add new line in my job entity instead of use line already in my database.
Any idea?

I guess $jobs is a Collection of Job, so you should implements methods to handle this collection.
If your entity declarations are correct (oneToMany, ManyToOne, uni/bi directional) you should have something like this :
class Bloc
{
// ...
protected $jobs;
public function __construct()
{
$this->jobs = new Doctrine\Common\Collections\ArrayCollection();
}
public function getJobs()
{
return $this->jobs;
}
public function setJobs($jobs)
{
$this->jobs = new Doctrine\Common\Collections\ArrayCollection();
foreach ($jobs as $job) {
$this->addJob($job);
}
return $this;
}
public function addJob(Job $job)
{
if (!$this->jobs->contains($job) {
$this->jobs->add($job);
// if needed for bi directional way
// $job->setBloc($this);
}
}
public function removeJob(Job $job)
{
// if you want
}
// ...
}

Related

Unit test Laravel middleware

I am trying to write unit tests for my middleware in Laravel. Does anyone know a tutorial, or have an example of this ?
I have been writing a lot of code, but there must be a better way to test the handle method.
Using Laravel 5.2, I am unit testing my middleware by passing it a request with input and a closure with assertions.
So I have a middleware class GetCommandFromSlack that parses the first word of the text field in my Post (the text from a Slack slash command) into a new field called command, then modifies the text field to not have that first word any more. It has one method with the following signature: public function handle(\Illuminate\Http\Request $request, Closure $next).
My Test case then looks like this:
use App\Http\Middleware\GetCommandFromSlack;
use Illuminate\Http\Request;
class CommandsFromSlackTest extends TestCase
{
public function testShouldKnowLiftCommand()
{
$request = new Illuminate\Http\Request();
$request->replace([
'text' => 'lift foo bar baz',
]);
$mw = new \App\Http\Middleware\GetCommandFromSlack;
$mw->handle($request,function($r) use ($after){
$this->assertEquals('lift', $r->input('command'));
$this->assertEquals('foo bar baz',$r->input('text'));
});
}
}
I hope that helps! I'll try to update this if I get more complicated middleware working.
To actually test the middleware class itself you can do:
public function testHandle()
{
$user = new User(['email'=>'...','name'=>'...']);
/**
* setting is_admin to 1 which means the is Admin middleware should
* let him pass, but oc depends on your handle() method
*/
$user->is_admin = 1;
$model = $this->app['config']['auth.model'];
/**
* assuming you use Eloquent for your User model
*/
$userProvider = new \Illuminate\Auth\EloquentUserProvider($this->app['hash'], $model);
$guard = new \Illuminate\Auth\Guard($userProvider, $this->app['session.store']);
$guard->setUser($user);
$request = new \Illuminate\Http\Request();
$middleware = new \YourApp\Http\Middleware\AuthenticateAdmin($guard);
$result = $middleware->handle($request, function(){ return 'can access';});
$this->assertEquals('can access',$result);
}
I thinking the best solution is just checking what happened after middleware. For example, the authentication middleware:
<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;
class Authenticate {
/**
* The Guard implementation.
*
* #var Guard
*/
protected $auth;
/**
* Create a new filter instance.
*
* #param Guard $auth
* #return void
*/
public function __construct(Guard $auth)
{
$this->auth = $auth;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
if ($this->auth->guest())
{
if ($request->ajax())
{
return response('Unauthorized.', 401);
}
else
{
return redirect()->guest('auth/login');
}
}
return $next($request);
}
}
And my test unit:
<?php
class AuthenticationTest extends TestCase {
public function testIAmLoggedIn()
{
// Login as someone
$user = new User(['name' => 'Admin']);
$this->be($user);
// Call as AJAX request.
$this->client->setServerParameter('HTTP_X-Requested-With', 'XMLHttpRequest');
$this->call('get', '/authpage');
$this->assertEquals(200, $response->getStatusCode());
}
}
I would do it in that way.
I was working on a localization Middleware that sets the app locale based on a URI segment, e.g. http://example.com/ar/foo should set the app local to Arabic. I basically mocked the Request object and tested as normal. Here is my test class:
use Illuminate\Http\Request;
use App\Http\Middleware\Localize;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class LocalizeMiddlewareTest extends TestCase
{
protected $request;
protected $localize;
public function setUp()
{
parent::setUp();
config(['locale' => 'en']);
config(['app.supported_locales' => ['en', 'ar']]);
$this->request = Mockery::mock(Request::class);
$this->localize = new Localize;
}
/** #test */
public function it_sets_the_app_locale_from_the_current_uri()
{
$this->request->shouldReceive('segment')->once()->andReturn('ar');
$this->localize->handle($this->request, function () {});
$this->assertEquals('ar', app()->getLocale());
}
/** #test */
public function it_allows_designating_the_locale_uri_segment()
{
$this->request->shouldReceive('segment')->with(2)->once()->andReturn('ar');
$this->localize->handle($this->request, function () {}, 2);
$this->assertEquals('ar', app()->getLocale());
}
/** #test */
public function it_throws_an_exception_if_locale_is_unsupported()
{
$this->request->shouldReceive('segment')->once()->andReturn('it');
$this->request->shouldReceive('url')->once()->andReturn('http://example.com/it/foo');
$this->setExpectedException(
Exception::class,
"Locale `it` in URL `http://example.com/it/foo` is not supported."
);
$this->localize->handle($this->request, function () {});
}
}
And here is my Middleware class:
namespace App\Http\Middleware;
use Closure;
class Localize
{
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #param integer $localeUriSegment
* #return mixed
*/
public function handle($request, Closure $next, $localeUriSegment = 1)
{
$locale = $request->segment($localeUriSegment);
if (in_array($locale, config('app.supported_locales')))
{
app()->setLocale($locale);
}
else
{
abort(500, "Locale `{$locale}` in URL `".$request->url().'` is not supported.');
}
return $next($request);
}
}
Hope that helps :)

must return a string value in zend2. How?

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);

How does this variable is not defined?

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?]

Zend Framework: How to unit test a model using Zend_Service_Twitter

I have been getting into Unit Testing with Zend Framework. I am getting used to the other things it provide but I am having a hard time understanding Mock Objects.
For this example, I am trying to use a Mock Object to test out my model.
<?php
class Twitter_Model_Twitter
{
private $_twitter;
/**
* Make the options injectable.
* __contruct($auth, $key)
*/
public function __construct()
{
$config = new Zend_Config_Ini(APPLICATION_INI, APPLICATION_ENV);
$key = $config->encryption->salt;
$iv_size = mcrypt_get_iv_size(MCRYPT_XTEA, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$password = mcrypt_decrypt(MCRYPT_XTEA, $key, $password, MCRYPT_MODE_ECB, $iv);
$this->_twitter = new Zend_Service_Twitter($username, $password);
}
public function verifyCredentials()
{
return $this->_twitter->account->verifyCredentials();
}
public function friendsTimeline($params)
{
return $this->_twitter->status->friendsTimeline($params);
}
}
For my unit test:
require_once ('../application/models/Twitter.php');
class Model_TwitterTest extends ControllerTestCase
{
/**
* #var Model_Twitter
*/
protected $_twitter;
public function testfriendsTimeline()
{
$mockPosts = array('foo', 'bar');
//my understanding below is:
//get a mock of Zend_Service_Twitter with the friendsTimeline method
$twitterMock = $this->getMock('Zend_Service_Twitter', array('friendsTimeline'));
/*
line above will spit out an error:
1) testfriendsTimeline(Model_TwitterTest)
Missing argument 1 for Mock_Zend_Service_Twitter_9fe2aeaa::__construct(), called in
/Applications/MAMP/bin/php5/lib/php/PHPUnit/Framework/TestCase.php on line 672 and
defined /htdocs/twitter/tests/application/models/TwitterTest.php:38
*/
$twitterMock->expects($this->once())
->method('friendsTimeline')
->will($this->returnValue($mockPosts));
$model = new Twitter_Model_Twitter();
$model->setOption('twitter', $twitterMock);
$posts = $model->friendsTimeline(array('count'=>20));
$this->assertEquals($posts, $mockPosts);
}
}
How would you test the following?
1) verifyCredentials()
2) friendsTimeline()
Thanks,
Wenbert
I am going to answer this question. I think I have made this work thanks to zomg from #zftalk.
Here is my new Twitter Model:
<?php
//application/models/Twitter.php
class Twitter_Model_Twitter
{
private $_twitter;
private $_username;
private $_password;
public function __construct(array $options = null)
{
if (is_array($options)) {
$this->setOptions($options);
$this->_twitter = new Zend_Service_Twitter($this->_username, $this->_password);
} else {
$twitterAuth = new Zend_Session_Namespace('Twitter_Auth');
$config = new Zend_Config_Ini(APPLICATION_INI, APPLICATION_ENV);
$key = $config->encryption->salt;
$iv_size = mcrypt_get_iv_size(MCRYPT_XTEA, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$password = mcrypt_decrypt(MCRYPT_XTEA, $key, $twitterAuth->password, MCRYPT_MODE_ECB, $iv);
$username = $twitterAuth->username;
$this->_twitter = new Zend_Service_Twitter($username, $password);
}
}
public function setOptions(array $options)
{
$methods = get_class_methods($this);
foreach ($options as $key => $value) {
$pieces = explode('_', $key);
foreach($pieces AS $piece_key => $piece_value) {
$pieces[$piece_key] = ucfirst($piece_value);
}
$name = implode('',$pieces);
$method = 'set' . $name;
//$method = 'set' . ucfirst($key);
if (in_array($method, $methods)) {
$this->$method($value);
}
}
return $this;
}
//I added this method. So that I could "inject"/set the $_twitter obj
public function setTwitter($obj)
{
$this->_twitter = $obj;
return $this;
}
public function verifyCredentials()
{
return $this->_twitter->account->verifyCredentials();
}
public function friendsTimeline($params)
{
return $this->_twitter->status->friendsTimeline($params);
}
//in the real code, more will go here...
}
And in my Unit Test, I have this:
<?php
// tests/application/models/TwitterTest.php
require_once ('../application/models/Twitter.php');
class Model_TwitterTest extends ControllerTestCase
{
public function testVerifyCredentials()
{
$stub = $this->getMock('Zend_Service_Twitter', array('verifyCredentials'),array(),'',FALSE);
//FALSE is actually the 5th parameter to flag getMock not to call the main class. See Docs for this.
//Now that I have set the $_twitter variable to use the mock, it will not call the main class - Zend_Rest_Client (i think)
$stub->expects($this->once())
->method('verifyCredentials');
$model = new Twitter_Model_Twitter();
//this is the part where i set the $_twitter variable in my model to use the $stub
$model->setOptions(array('twitter'=>$stub));
$model->verifyCredentials();
}
}
Anyways, I think I got it working.
1) The unit test no longer tried to connect to twitter.com:80
2) After I got the setOptions() working in the Twitter_Model, $model->verifyCredentials() in my unit test was successfully called.
I will wait for others in Stackoverflow to confirm that is the right answer. For the meantime, would like to hear from you guys.
Thanks!!!

Zend Framework: How should I unit test my Mapper in Zend_Db?

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.