Laravel: Can't access methods in Model from Controller - methods

I'm having an issue with one of my controllers accessing the methods within a model.
I have a controller (application>controllers>event.php) with an index method:
class Event_Controller extends Base_Controller {
public $layout = 'layouts.default';
public $restful = true;
public function get_index()
{
$category = (isset($_GET['category']))? $_GET['category'] : NULL;
$date = (isset($_GET['date']))? $_GET['date'] : NULL;
$county = (isset($_GET['county']))? $_GET['county'] : NULL;
$events = Event::get_event_list($category, $date, $county);
$this->layout->title = 'Events';
$this->layout->nest('content', 'event.index', array(
//'data' => $some_data
));
}
}
And the model (application>models>event.php):
class Event extends Eloquent{
public static function get_event_list($category = null, $month = null, $county = null)
{
$events = DB::table('events');
if($month)
$events->where('dtDateTime', 'LIKE', $month.'-%');
if($category)
$events->where('strCategories', 'LIKE', '%['.$category.']%');
if($county)
$events->where('strCounty', 'LIKE', '%'.$tag.'%');
return $events->order_by('dtDateTime', 'DESC')->get();
}
}
If I change the model name in the call to the method in the controller (ie Eventsx::....) I get an error that the model doesn't exist so I know it can find the model, however when I try and run this (or with a call to any other method in the Model), I get the error:
Call to undefined method Laravel\Event::get_event_list()
I have similar controllers accessing similar methods in their models but for some reason, it is not playing ball here. The controller can access methods in other Models with no issues.
Here are my routes:
Route::get('/events', array('as' => 'event', 'uses' => 'Event#index'));
Route::get('/events/(:any)', array('as' => 'event', 'uses' => 'Event#event'));
Can anyone see anything glaringly obvious that I'm doing wrong here?
Thanks

I worked it out. class Event is already taken by laravel. I renamed my model and everything worked fine

Related

Laravel partial mock doesn't work with Eloquent model

I got this error when I try to partially mock an Eloquent model:
Received Mockery_1_App_Models_Invoice::__construct(), but no expectations were specified
I only want to mock the method "getPdf" of my model.
My service
class MyService
{
public function sendPdf($invoiceId)
{
// Invoice::class extend: Illuminate\Database\Eloquent\Model
$invoiceRepository = Container::getInstance()->make(Invoice::class);
$invoice = $invoiceRepository->find($invoiceId);
$invoice->getPdf();
}
}
The test
it('a test', function () {
$filePath = '/path-of-a-pdf.pdf';
$this->partialMock(Invoice::class, function (MockInterface $mock) use ($filePath) {
$mock->shouldReceive('getPdf')->atLeast()->once()->andReturn($filePath);
});
$invoice = Invoice::factory()->create([
'type' => 'invoice'
]);
$myService = new MyService();
$myService->sendPdf($invoice->id);
});
If I try with a full mock, it works but I don't want to mock everything like the method "find".
Do you have an idea of this problem?
I found this issue but I don't really find a solution to this problem.
Thank you in advance for your help.

Laravel model function best prickets

im new in Laravel , I have an issue as below
I make in category model query to check is category is exist or not
as below
public function scopeIsExist($query ,$id)
{
return $query->where(['deleted' => 1, 'id' => $id])->orderBy('id', 'DESC')->first();
}
and my controller is
public function edit($id)
{
$dataView['category'] = Category::IsExist($id);
if(!$dataView['category'])
{
return view('layouts.error');
}else{
$dataView['title'] = 'name';
$dataView['allCategories'] = Category::Allcategories()->get();
return view('dashboard.category.edit')->with($dataView);
}
}
my problem is when I use method isEXIST if id not found it not redirect to error page but ween i remove ISEXIST AND replace it as below
$dataView['category'] = Category::where(['deleted' => 1, 'id' => $id])->orderBy('id', 'DESC')->first();
it work well .
can any one help me
That's because local scope should return an instance of \Illuminate\Database\Eloquent\Builder. You should remove the first() in the scope and put it in the controller.
Redefine your scope like so:
public function scopeIsExist($query ,$id)
{
return $query->where(['deleted' => 1, 'id' => $id])->orderBy('id', 'DESC');
}
In your controller edit method:
$dataView['category'] = Category::IsExist($id)->first();
You can have a look to the doc for local scopes https://laravel.com/docs/8.x/eloquent#local-scopes

Create Relationship inside the create function

I have a model that has a one to many relationship to the versions of the description.
In my Controller
$tag = Tags::create([
'name' => $request->get('name'),
'user_id' => \Auth::id(),
]);
$tag->update([
'content' => $request->get('description')
]);
In my Model:
public function setContentAttribute(string $value)
{
$this->versions()->create([
'user_id' => \Auth::id(),
'value' => $value
]);
}
So I can't put content directly as an attribute in the create method because there is no Model right now.
But is it possible to overwrite the create Method?
When I try to overwrite something like this in my Model it will do an infinity loop
public static function create($attr) {
return parent::create($attr);
}
So my question is if it is possible to have something like this:
$tag = Tags::create([
'name' => $request->get('name'),
'user_id' => \Auth::id(),
'content' => $request->get('content')
]);
and in the Model:
public static function create($attr) {
$value = $attr['content'];
$attr['content'] = null;
$object = parent::create($attr);
$object->content = $value;
$object->save();
return $object;
}
Update
I didn't overwrite the create method but called it customCreate. So there is no infinity loop anymore and I can pass all variables to the customCreate function that handles the relationships for me.
Solution
After reading the changes from 5.3 to 5.4 it turns out that the create method was moved so you don't have to call parent::create() anymore.
The final solution is:
public static function create($attr) {
$content = $attr['content'];
unset($attr['content']);
$element = static::query()->create($attr);
$element->content = $content;
$element->save();
return $element;
}
I don't see why not and you could probably implement a more general approach? Eg. checking if set{property}Attribute() method exists, if it does - use it to assign a value, if it doesn't - use mass assigning.
Something like:
public static function create($attr) {
$indirect = collect($attr)->filter(function($value, $property) {
return method_exists(self::class, 'set' . camel_case($property) . 'Attribute');
});
$entity = parent::create(array_diff_key($attr, $indirect->toArray()));
$indirect->each(function($value, $property) use ($entity) {
$entity->{$property} = $value;
});
$entity->save();
return $entity;
}
I haven't really tested it but it should work. I use something like this in one of my Symfony apps.

Laravel Model to View - Undefined variable

I'm sure I'm missing something blindingly obvious but cannot see to get the division name to appear on my view.
It keeps returning Undefined variable: division_name
DIVISON.PHP (Model)
<?php
class Division extends \Eloquent {
protected $table = 'divisions';
public function scopeGetDivisionName($query, $slug)
{
return $query->select('division_name')
->join('division_industry_job', 'division_industry_job.division_id', '=', 'divisions.id')
->join('industryjobs', 'division_industry_job.industry_job_id', '=', 'industryjobs.id')
->where('industryjobs.slug', '=', $slug);
}
}
JOBCONTROLLER.PHP (Controller)
public function showdivisionjob($slug)
{
$job = IndustryJob::where("slug", "=", $slug)->first();
$division_name = Division::getDivisionName($slug)->firstOrFail();
return View::make('job')->with('job', $job, $division_name);
}
JOB.BLADE.PHP (View)
{{$division_name->division_name}}
{{$job->job_title}}
You're not passing the variable to your view properly.
// This won't work
return View::make('job')->with('job', $job, $division_name);
It should be
return View::make('job')->with('job', $job)
->with('division_name', $division_name);
Or
return View::make('job', array(
'job' => $job,
'division_name' => $division_name
));
You can use also the compact method for passing variables to your view :
public function showdivisionjob($slug)
{
$job = IndustryJob::where("slug", "=", $slug)->first();
$division_name = Division::getDivisionName($slug)->firstOrFail();
return View::make('job', compact('job', 'division_name'));
}

Accessing public methods in a Doctrine model (Code Igniter)

I'm trying to add pagination to my code igniter project. I am using Doctrine for my models and I can't seem to use $this->load->model('gif') to access the methods in my controller. I guess a Doctrine model acts differently, but surely there is a way to call the public methods?
Here is my controller:
<?php
class View extends Controller
{
function index()
{
// load pagination class
$gifs = Doctrine::getTable('Gif')->findAll();
$this->load->library('pagination');
$config['base_url'] = base_url().'view/';
$config['total_rows'] = count($gifs);
$config['per_page'] = '5';
$config['full_tag_open'] = '<p>';
$config['full_tag_close'] = '</p>';
$this->pagination->initialize($config);
//load the model and get results
//$this->load->model('gif');
$data['results'] = $gifs->getGifs($config['per_page'],$this->uri->segment(2));
// load the view
$this->load->view('front_images', $data);
}
}
Here is my model
<?php
class Gif extends Doctrine_Record {
public function setTableDefinition()
{
$this->hasColumn('photo_path', 'string', 255, array('unique' => true, 'notnull' => true));
$this->hasColumn('title', 'string', 255, array('notnull' => true));
$this->hasColumn('user_id', 'integer', 4);
$this->hasColumn('token', 'string', 255);
}
public function setUp()
{
$this->actAs('Timestampable');
$this->hasOne('User', array(
'local' => 'user_id',
'foreign' => 'id'
));
}
public function preInsert($event)
{
$this->token = (sha1(rand(11111, 99999)));
}
public function numGifs() {
$result = Doctrine_Query::create()
->select('COUNT(*) as num_gifs')
->from('Gif')
->fetchOne();
return $result['num_gifs'];
}
public function getGifs($offset, $limit)
{
$gifs = Doctrine_Query::create()
->from('Gif g')
->orderBy('g.created_at DESC')
->limit($limit)
->offset($offset)
->execute();
return $gifs;
}
}
How can I call the numGifs and getGifs methods from that controller? Thanks in advance!
I am also using CI in conjunction with doctrine. for reference i am following the tuto located at http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup .
I don't know if you followed similar steps but using this approach models do not need to be loaded but rather instantiated.
for eg.
$g = new Gif();
$g = $g->getGifs();
(although in this particular case
- $g expects only one row
- Am not sure if we can define getter functions inside the model representing the table itself. in the tuto am following the model contains only the db table definition as well as any relationships)
hope this helps.

Resources