Call a custom model method from controller laravel4 - php

I have a model like this:
class Event extends Eloquent
{
protected $softDelete = true;
public function scopeSearchEvents($search_criteria)
{
return Event::whereIn('title',$search_criteria)
->orWhereIn('description',$search_criteria)
->whereApproved('1')
->orderBy('event_date','desc')
->get();
}
}
And im calling it from the controller like this:
$data = Event::search($search_criteria);
But it gives this error:
Symfony \ Component \ Debug \ Exception \ FatalErrorException
Call to undefined method Illuminate\Events\Dispatcher::search()
What is the best way of calling a custom model method from your controller?

Make changes to your method as given below:
public function scopeSearchEvents($query, $search_criteria)
{
return $query->whereIn('title', $search_criteria)
->orWhereIn('description', $search_criteria)
->whereApproved('1')
->orderBy('event_date','desc');
}
Then call it like searchEvents not search:
// Don't use Event as your model name
$data = YourModel::searchEvents($search_criteria)->get();
Also make sure that, you want to use whereIn instead of where('title', 'LIKE', "% $search_criteria") and so.
Update:
You should change the model name from Event to anything else because Laravel has it's core Event class, actually a Facade which is mapped to 'Illuminate\Support\Facades\Event'.

Have a look at the app.php:
'aliases' => array(
...
'Event'=> 'Illuminate\Support\Facades\Event',
...
);
"Event" is defined as an alias. That's why your Event calls "Illuminate\Support\Facades\Event".
Now if you want to use your event model without typing the namespace to call methods create an alias like:
'MyEvent' => 'App\Models\Event',
and then:
MyEvent::create();

Related

Laravel error: Target [Illuminate\View\Engines\EngineInterface] is not instantiable

I'm creating an abstract class that will grab the contents of a view using Laravel's View class. But I'm getting the following error when trying to run a method from a class that extends it:
Illuminate \ Container \ BindingResolutionException
Target [Illuminate\View\Engines\EngineInterface] is not instantiable.
Here's my code:
PdfReport.php
use Illuminate\View\View as View;
abstract class PdfReport {
private $view;
function __construct(View $view)
{
$this->view = $view;
}
public function render($reportView, $report)
{
$this->view->make('report.pdf.' . $reportView, ['report' => $report])->render();
}
}
EslReport.php
<?php namespace Reports\PdfReports;
class EslPdfReport extends PdfReport {
public function renderReport($report)
{
return $this->render('esl', $report);
}
}
Then I'm running my code in routes.php for testing purposes as follows:
use Reports\PdfReports\EslPdfReport;
Route::get('pdftest', array(
'as' => 'pdftest',
function(){
$eslReport = App::make('Reports\PdfReports\EslPdfReport');
$eslReport->renderReport(EslReport::find(1));
}
));
I'm not quite understanding if I'm doing something wrong with the dependency injection for the view in the abstract class, it's all pretty new concepts to me, so any help would be most appreciated.
Also I asked this question on laracasts forum if it helps: https://laracasts.com/discuss/channels/general-discussion/confusion-about-constructors-in-abstract-classes
Instead of Illuminate\View\View you need to inject Illuminate\View\Factory:
use Illuminate\View\Factory as View;
Here's a reference of facade classes and there actual underlying class you need to use when working with DI

Laravel event won't work

I have setup an event that does some stuff once a user registers. Updating and inserting etc, but it won't work.
I get the error:
Symfony \ Component \ Debug \ Exception \ FatalErrorException (E_ERROR)
Class 'EventHandlers\Handlers\User' not found
I don't know why it won't work. But I haven't misspelled anything, because if I eg "return 'test';" in my event it works, but it won't update my userModel
In my Usercontroller:
$user = User::create([
some values..
]);
Event::fire('user.create', $user);
Now I subscribe to events in my app/start/global.php, I autoload the folder using PSR-4
Event::subscribe('EventHandlers\Handlers\UserAccountActions');
Event::subscribe('EventHandlers\Handlers\ProductActions');
Event::subscribe('EventHandlers\Handlers\CommentActions');
And in my event/listener file
<?php namespace EventHandlers\Handlers;
class UserAccountActions {
// Listeners
public function subscribe($events)
{
$events->listen('user.create', 'EventHandlers\Handlers\UserAccountActions#onCreate');
}
// happens when a user register
public function onCreate($user)
{
$user->api_key = User::createApiKey();
}
}
In your EventHandlers\Handlers\UserAccountActions you refer to User as it was in the same namespace. You need to add a backslash \ to access the User class in the global namespace:
// happens when a user register
public function onCreate($user)
{
$user->api_key = \User::createApiKey();
}
(Or specify the namespace if the User model is in one. e.g. \Models\User)
Alternatively you can also import the model with a use statement:
use User;
class UserAccountActions {

Where is the Input class in Laravel 4? (or How to find the actual classes of Facades?)

I am trying to trace down methods of the Input class in Laravel 4 but I am not able to find the real class.
In app.php we have Alias of Input
'Input' => 'Illuminate\Support\Facades\Input',
But it takes me to file which is just a facade.
class Input extends Facade {
public static function get($key = null, $default = null)
{
return static::$app['request']->input($key, $default);
}
protected static function getFacadeAccessor() { return 'request'; }
}
Where is the actual file and how to trace down Facades to Actual Classes in Laravel?
check http://laravel.com/docs/4.2/facades and scroll down to the bottom to see each facade, class name and the IoC binding
Input facade is in fact Request: Illuminate\Http\Request. You can get all facades classes at http://laravel.com/docs/4.2/facades#facade-class-reference

Mocking in controller tests with Laravel model binding

I'm using model binding within my routes to pass models into my controller actions and would like to be able to write tests. It would be preferable if it wasn't required for the test to hit the database.
The model is bound using the username in this example, and then used in the definition of the routes.
// routes.php
Route::model('user', function($value, $route)
{
return User::whereUsername($value)->firstOrFail();
});
Route::get('users/{user}', 'UsersController#show');
In my controller the bound user is passed to the action.
// UsersController.php
function show(User $user)
{
return View::make('users.show', compact('user');
}
Now, in my tests I'm attempting to mock the User.
// UsersControllerTest.php
public function setUp()
{
parent::setUp();
$this->mock = Mockery::mock('Eloquent', 'User');
$this->app->instance('User', $this->mock);
}
public function testShowPage()
{
$this->mock->shouldReceive('whereSlug')->once()->andReturn($this->mock);
$this->action('GET', 'UsersController#show');
$this->assertResponseOk();
$this->assertViewHas('user');
}
When running this test, I get the following error:
ErrorException: Argument 1 passed to UsersController::show() must be an instance of User, instance of Illuminate\Database\Eloquent\Builder given
I'd also like to be able to use return User::firstByAttribtues($value); but Mockery won't let me mock a protected method - is there any way I can get around this?
I had to dig thru Mockery's source code to find this, but have you looked at shouldAllowMockingProtectedMethods ?
Ie, to mock class foo and allow protected methods to be mocked:
$bar = \Mockery::mock('foo')->shouldAllowMockingProtectedMethods();
// now set your expectations up
and then keep going from there.
Not sure why you're not getting an error like unexpected method "firstOrFail" called. But, at first glance, I think the problem is that your model route defined in routes.php is also calling the firstOrFail method.
So, your test should look something like this:
public function testShowPage()
{
$stubQuery = \Mockery::mock('Illuminate\Database\Eloquent\Builder');
$this->mock->shouldReceive('whereSlug')->once()->andReturn($stubQuery);
$stubQuery->shouldReceive('firstOrFail')->andReturn($this->mock);
$this->action('GET', 'UsersController#show');
$this->assertResponseOk();
$this->assertViewHas('user');
}

Zend database adapter - register in bootstrap.php?

I am trying to register my default database adapter in my bootstrap.php file so that I can access it where ever I am. This is my code so far:
//bootstrap.php
protected function _initDb()
{
$dbAdapter = Zend_Db::factory(Zend_Registry::get('configuration')
->resources->db->adapter,
Zend_Registry::get('configuration')
->resources->db->params->toArray());
Zend_Registry::set('dbAdapter', $dbAdapter);
Zend_Db_Table_Abstract::setDefaultAdapter($dbAdapter);
}
I am then trying to call it in one of my models by saying:
//exampleModel.php
$select = $this->_getDbAdapter()
->select()
->from(array('t' => $this->_getTable()->getName()),
array('name'))....
However I am just getting the error:
Call to undefined method Application_Model_Example::_getdbAdapter() in...
So obviously it is looking for it within my current class and can't find it...
You need this in your Model_Example
public function _getSqlAdapter()
{
return Zend_Registry::get('dbAdapter');
}
Or directly call Zend_Db_Table::getDefaultAdapter() instead of $this->_getDbAdapter()
In the code provided you don't appear to be calling it the adapter from the registry. You would need to use Zend_Registry::get('dbAdapter');
What class does Application_Model_Example extend?
I have Zend_Db_Table::setDefaultAdapter($dbAdapter); in my bootstrap (notice its Zend_Db_Table, not Zend_Db_Table_Abstract).
Then in my models, I would just use
$select = $this->->select()
->from(array('t' => $this->_getTable()->getName()), array('name'))....
assuming your model extends Zend_Db_Table?

Categories