General attribute accessor for a model in Laravel? - php

Is there a way to set up an accessor that is executed for all model attributes? Im using laravel 5.
For example:
class FooBar extends Model
{
/**
* foo accessor
*/
public function getFooAttribute($value){
return doSomething($value);
}
/**
* bar accessor
*/
public function getBarAttribute($value){
return doSomething2($value);
}
/**
* Access all attributes for this model (?)
*/
public function getAllAttributes($value){
return strtoupper($value);
}
}

Related

Adding Setters and Getters to Laravel Model

If I want an Eloquent Model class to have setters and getters for the sake of implementing an interface does the following approach make sense or is there a 'laravel' approach to the problem
class MyClass extends Model implements someContract
{
public function setFoo($value) {
parent::__set('foo', $value);
return $this;
}
public function getFoo() {
return parent::__get('foo');
}
}
You are probably looking for accessors (getters) and mutators (setters).
Example of an accessor (getter) in Laravel:
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
Example of a mutator (setter) in Laravel:
public function setFirstNameAttribute($value)
{
$this->attributes['first_name'] = strtolower($value);
}
For new laravel you can do this in model :
/**
* Interact with the user's first name.
*
* #param string $value
* #return \Illuminate\Database\Eloquent\Casts\Attribute
*/
protected function firstName(): Attribute
{
return Attribute::make(
get: fn ($value) => ucfirst($value),
set: fn ($value) => strtolower($value),
);
}
Wanna know more? see at :
https://laravel.com/docs/9.x/eloquent-mutators#defining-a-mutator

Laravel 5.0 model test Mockery unable to mock method/static method does not exist?

I am using Laravel 5.0 to create phpunit test alongside the actual model.
I get errors in phpunit tests but no errors when controller calls the model and it returned the desired data.
sample.php
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class sample extends Model {
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'sample';
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = ['id','username','details','image'];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
public static function test()
{
return "Returned Text.";
}
public static function gettest()
{
return self::test();
}
public static function getItem()
{
return self::orderBy('username','asc')->get();
}
public static function findItem($id)
{
return self::find($id);
}
}
SampleTest.php
<?php namespace App;
use Mockery as m;
class SampleTest extends \PHPUnit_Framework_TestCase {
protected function setUp()
{
$this->mock = m::mock('App\sample')->makePartial();
}
protected function tearDown()
{
m::close();
}
/** #test */
public function should_return_string()
{
$response = $this->mock->test();
var_dump("test() returns :".$response);
}
/** #test */
public function should_return_string_from_test_function()
{
$response = $this->mock->gettest();
var_dump("gettest() returns :".$response);
}
/** #test */
public function should_return_mocked_data()
{
$this->mock->shouldReceive('test')->andReturn('Return Mocked Data');
$response = $this->mock->gettest();
var_dump("gettest() returns :".$response);
}
/** #test */
public function should_return_some_data_using_this_mock()
{
$this->mock->shouldReceive('get')->andReturn('hello');
$response = $this->mock->getItem();
}
}
Problem
When I use controller to call the model, it returned the desired data.
When I run phpunit on command prompt:-
test function is not mocked properly as it still returns the original string
getItem and findItem functions return an error saying
1) App\SampleTest::should_return_some_data_using_this_mock
BadMethodCallException: Static method Mockery_0_App_sample::getItem()
does not exist on this mock object
Question
How can I mock the function properly? Why it is saying the error code as shown above? Where was I doing it wrong?
Any help will be much appreciated.
Note: Test assertions is removed and replaced with var_dump to see the output on the command prompt.

Laravel after composer update model method call undefined

I am working on a project with Laravel 4.2 and I created some models and controllers and called model function from controller, the problem is after composer update command it displays this error: Call to undefined method Department::getAllParent() but before composer update it works fine. You think what is the problem with this issue? thanks in advance
Model code:
class Department extends Eloquent{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'department';
public static function getAll()
{
$table = DB::table('department');
$object = $table->get();
return $object;
}
public static function getAllParent()
{
$table = DB::table('department');
$table->where('parent',0);
$object = $table->get();
return $object;
}
}
And Controller code:
class DepartmentController extends BaseController
{
/*
Getting all records from department
#param: none
#Accessiblity: public
#return: Object
*/
public function getAllDepartment()
{
//get data from model
$deps = Department::getAllParent();
$depAll = Department::getAll();
//load view for users list
return View::make("department.dep_list")->with('deps',$deps)->with('all',$depAll);
}
}
Don't think this is related to your issues but this might be a better way to handle these queries. you are using Eloquent and setting the table parameter. why not use Eloquent's build in power?
class Department extends Eloquent{
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'department';
public static function getAll()
{
return Department::get();
}
public static function getAllParent()
{
return Department::where('parent', 0)->get();
}
}
I think you might also be able to use $this->get(); but I can't test right now.

how to Inject a Sentry 2 User Model into a controller - laravel 4

How do you inject a Sentry 2 User model into a laravel 4 controller using IoC?
for example i would like the following
class myController extends BaseController {
/**
* creates a list of MyModel Models
*
* #return View
*/
public function getIndex( User $user )
{
// fetch models
$models = MyModel::all();
// Show the page
return View::make('my-views.the-view', compact('models', 'user'));
}
}
This is how I like to do it:
class myController extends BaseController {
$protected $user
/**
* creates a list of MyModel Models
*
* #return View
*/
function __construct(User $user){
parent::__construct();
$this->user = $user;
}
public function getIndex()
{
// fetch models
$models = MyModel::all();
// Show the page
return View::make('my-views.the-view', compact('models', 'user'));
}
}
You can also do it in the method, but... well, give this a good read, too: http://fabien.potencier.org/article/11/what-is-dependency-injection

laravel abstract method fatal exception error

I am using the User class included with laravel 4. I am trying to store a new question that belongs to the user and the user needs to be logged in to create. when I call the questions controller action store I get the following error
Class User contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Illuminate\Auth\UserInterface::getAuthPassword, Illuminate\Auth\Reminders\RemindableInterface::getReminderEmail)
I have read a bit on abstract methods in php and while I don't completely understand them the error itself gives two solutions to the problem, declare the class abstract of implement the remaing methods. I am guessing that since this is the model class that ships with laravel that the correct solution is not to change its declaration to abstract but to implement the remaining methods. How do I do this correctly in this case and going forward?
User Model
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class User extends BaseModel implements UserInterface, RemindableInterface {
protected $guarded = [];
public static $rules = array(
'username' => 'required|unique:users|alpha_dash|min:4',
'password' => 'required|alpha_num|between:4,8|confirmed',
'password_confirmation'=>'required|alpha_num|between:4,8'
);
public function Questions($value='')
{
return $this->hasMany('Question');
}
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password');
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier()
{
return $this->getKey();
}
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->password;
}
/**
* Get the e-mail address where password reminders are sent.
*
* #return string
*/
public function getReminderEmail()
{
return $this->email;
}
}
Questions Controller
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function postStore()
{
$validation = Question::validate(Input::all());
if($validation->passes()) {
Question::create(array(
'question'=>Input::get('question'),
'user_id'=>Auth::user()->id
));
return Redirect::Route('home')
->with('message', 'Your question has been posted.');
} else {
return Redirect::to('user/register')->withErrors($validation)
->withInput();
}
}
edit 1: The error message includes '(Illuminate\Auth\UserInterface::getAuthPassword, Illuminate\Auth\Reminders\RemindableInterface::getReminderEmail)' these two methods are in my user.php as publice functions as you can see above, so do I need to do something else to 'implement' them?
edit 2:
Laravel Src UserInterface Class
<?php namespace Illuminate\Auth;
interface UserInterface {
/**
* Get the unique identifier for the user.
*
* #return mixed
*/
public function getAuthIdentifier();
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword();
}
laravel src RemindableInterface class
<?php namespace Illuminate\Auth\Reminders;
interface RemindableInterface {
/**
* Get the e-mail address where password reminders are sent.
*
* #return string
*/
public function getReminderEmail();
}
edit 3:
php.ini related to error reporting
; error_reporting
; Default Value: E_ALL & ~E_NOTICE
; Development Value: E_ALL | E_STRICT
; Production Value: E_ALL & ~E_DEPRECATED
error_reporting = E_ALL
; Eval the expression with current error_reporting(). Set to true if you want
; error_reporting(0) around the eval().
; http://php.net/assert.quiet-eval
;assert.quiet_eval = 0
basemodel class
<?php
class Basemodel extends Eloquent {
public static function validate($data) {
return Validator::make($data, static::$rules);
}
}
?>
edit 4;
Adding correct model class as it was when giving the error and how it is now with the fix
<?php
use Illuminate\Auth\UserInterface;
use Illuminate\Auth\Reminders\RemindableInterface;
class Question extends BaseModel implements UserInterface, RemindableInterface {
protected $guarded = [];
public static $rules = array(
'questions'=>'required|min:10|max:255',
//'solved'=>'in:0,1',
);
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'questions';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('');
/**
* Get the unique identifier for the question.
*
* #return mixed
*/
public function getAuthIdentifier()
{
return $this->getKey();
}
public function user()
{
return $this->belongsTo('User');
}
}
add this to fix
/**
* Get the password for the user.
*
* #return string
*/
public function getAuthPassword()
{
return $this->password;
}
/**
* Get the e-mail address where password reminders are sent.
*
* #return string
*/
public function getReminderEmail()
{
return $this->email;
}
Perhaps it's easiest to answer this with an example. Say I have the following classes:
abstract class ClassB {
public abstract function foo();
}
class ClassA extends ClassB {}
$a = new ClassA();
Running this code will result in the following error:
Fatal error: Class ClassA contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (ClassB::foo)
This means I'm missing an implementation of foo() (defined in ClassB) in ClassA. Abstract methods can only be defined in abstract classes, and mean that any non-abstract derived class must expose a full implementation - which ClassA doesn't in this case. The above example can be fixed by changing ClassA to
class ClassA extends ClassB {
// implementation of abstract ClassB::foo().
public function foo() {
echo 'Hello!';
}
}
Back to your example. Your User class extends BaseModel. Depending on whether BaseModel extends another abstract class, it will contain two methods defined as abstract that your User class is missing. You need to find these methods - my error message explicitly told me what I was missing - and implement them in User.

Categories