I have a service-providers here as well as http://dfg.gd/blog/decoupling-your-code-in-laravel-using-repositiories-and-services
My ServiceProvider:
class UsersRepositoryServiceProvider extends ServiceProvider
{
public function register()
{
$this->app->bind('App\Repositories\Users\UsersInterface', function($app)
{
return new UsersRepository(new User);
});
}
And i get error: Call to a member function find() on a non-object
My Repository:
use \Illuminate\Database\Eloquent\Model;
//..
protected $usersModel;
public function __consturct(Model $users)
{
$this->usersModel = $users;
}
/**
* Get user by id
*
* #param mixed $userId
* #return Model
*/
public function getUserById($userId)
{
return $this->convertFormat($this->usersModel->find($userId));
}
__consturct is misspelled.
correct is __construct
Related
I am trying to understand the usage and difference of boot and booted.
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
protected static function boot() {
parent::boot();
static::creating(function ($user) {
});
}
protected static function booted() {
parent::booted();
static::creating(function ($user) {
});
}
}
When and where should be this two function called?
Actually answer is in the Eloquent model itself:
protected function bootIfNotBooted()
{
if (! isset(static::$booted[static::class])) {
static::$booted[static::class] = true;
$this->fireModelEvent('booting', false);
static::booting();
static::boot();
static::booted();
$this->fireModelEvent('booted', false);
}
}
/**
* Perform any actions required before the model boots.
*
* #return void
*/
protected static function booting()
{
//
}
/**
* Bootstrap the model and its traits.
*
* #return void
*/
protected static function boot()
{
static::bootTraits();
}
/**
* Perform any actions required after the model boots.
*
* #return void
*/
protected static function booted()
{
//
}
I tried both, I think there are just the same; just that boot will run first and it requires to call extra parent::boot()
protected static function boot()
{
parent::boot();
self::creating(function (Outlet $outlet): void {
Log::debug("#boot");
$outlet->name = "boot";
});
}
protected static function booted()
{
self::creating(function (Outlet $outlet): void {
Log::debug("#booted");
$outlet->name = "booted";
});
}
Normally we can simplify finding User by id logic in controller by injecting the User Class in parameter. Like this:
class UserController extends Controller
{
public function show(User $id)
{
return $user;
}
}
But now I must treat the Id to find like this:
<?php
namespace App\Http\Controllers;
class UserController extends Controller
{
public function show(User $id)
{
$preformattedId = '98'.$id;
$user = User::find($preformattedId );
return $user;
}
}
My basic question is: how I can achieved that same trick to my preformatted id in below code like the above code?
Note: I have to use the Id this way because i work with legacy database that actually adding that '98' prefix in every Id, despite that we only use characters after that prefix.
You can use Inversion of Control by using explicit binding on your router.
In your RouteServiceProvider
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
parent::boot();
Route::bind('user', function ($value) {
return User::find('98'.$value);
});
}
Or in your User model
/**
* Retrieve the model for a bound value.
*
* #param mixed $value
* #param string|null $field
* #return \Illuminate\Database\Eloquent\Model|null
*/
public function resolveRouteBinding($value, $field = null)
{
return $this->find('98'.$value);
}
https://laravel.com/docs/7.x/routing#explicit-binding
You can share your route file ?
But if your file is
Route::get('user/{id}', 'UserController#show');
When you use
class UserController extends Controller
{
public function show(User $id)
{
// you don't need use find function, it is make automatic by laravel
$user = $id;
return $user;
}
}
if you want to get id, just remove User type inside show parameter
class UserController extends Controller
{
public function show($id)
{
$preformattedId = '98'.$id;
$user = User::find($preformattedId );
return $user;
}
}
This is how I create helper (App\Helpers\Settings.php)
namespace App\Helpers;
use Illuminate\Database\Eloquent\Model;
class Settings {
protected $settings = [];
public function __construct() {
$this->settings['AppName'] = 'Test';
}
/**
* Fetch all values
*
* #return mixed
*/
public function getAll () {
return $this->settings;
}
}
Creating facade (App\Helpers\Facades\SettingsFacade.php)
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Settings extends Facade {
protected static function getFacadeAccessor() {
return 'Settings';
}
}
Creating Service Provider (App\Providers\SettingsServiceProvider.php)
namespace App\Providers;
use Illuminate\Support\Facades\App;
use Illuminate\Support\ServiceProvider;
class SettingsServiceProvider extends ServiceProvider {
/**
* Bootstrap the application events.
*
* #return void
*/
public function boot() {
}
/**
* Register the service provider.
*
* #return void
*/
public function register() {
App::bind( 'Settings', function () {
return new \App\Helpers\Settings;
});
} */
}
Registering provider (App\Providers\SettingsServiceProvider::class)
Creating alias: 'Settings' => App\Facades\Settings::class
Running composer dump-autoload
Trying to use facade Settings::getAll();
Getting error Class 'App\Http\Controllers\Settings' not found
Can’t figure out why I cannot create facade and getting that error
try this one.
App\Helpers\Settings.php
namespace App\Helpers;
use Illuminate\Database\Eloquent\Model;
class Settings {
protected $settings = [];
public function __construct() {
$this->settings['AppName'] = 'Test';
}
/**
* Fetch all values
*
* #return mixed
*/
public function getAll () {
return $this->settings;
}
}
App/Http/Controllers/XyzController.php
use Facades\App\Settings;
class XyzController extends Controller
{
public function showView()
{
return Settings::getAll();
}
}
web.php
Route::get('/','XyzController#showView');
use Facades\App\Helpers\Settings;
Route::get('/direct',function() {
return Settings::getAll();
});
use laravel Real time facades
so i am new in Laravel.
I want to use repository pattern, and here my problem:
here is my interface:
namespace Repositories\User;
interface IUserRepository
{
public function getAllUsers();
}
here my class:
namespace Repositories\User;
use models\User;
class UserRepository implements IUserRepository
{
public function getAllUsers()
{
return User::all();
}
}
here my controller:
class UserController extends \BaseController {
protected $user;
public function __contruct(IUserRepository $user)
{
$this->user = $user;
}
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
$users = $this->user->getAllUsers();
return View::make('index');
}
}
i register it in boostrap\start.php
App::bind('Repositories\User\IUserRepository', 'Repositories\User\UserRepository');
i think it can run smooth but it is a result i get :( :
Call to a member function getAllUsers() on a non-object
$users = $this->user->getAllUsers();
So why? :(( Thanks for helping!
If you infect that repo, then use namespace:
public function __contruct(Repositories\User\IUserRepository $user)
{
$this->user = $user;
}
I'm trying to override my Post class's save() method so that I can validate some of the fields that will be saved to the record:
// User.php
<?php
class Post extends Eloquent
{
public function save()
{
// code before save
parent::save();
//code after save
}
}
When I try and run a this method in my unit testing I get the following error:
..{"error":{"type":"ErrorException","message":"Declaration of Post::save() should be compatible with that of Illuminate\\Database\\Eloquent\\Model::save()","file":"\/var\/www\/laravel\/app\/models\/Post.php","line":4}}
Create Model.php class which you will extend in another self-validating models
app/models/Model.php
class Model extends Eloquent {
/**
* Error message bag
*
* #var Illuminate\Support\MessageBag
*/
protected $errors;
/**
* Validation rules
*
* #var Array
*/
protected static $rules = array();
/**
* Validator instance
*
* #var Illuminate\Validation\Validators
*/
protected $validator;
public function __construct(array $attributes = array(), Validator $validator = null)
{
parent::__construct($attributes);
$this->validator = $validator ?: \App::make('validator');
}
/**
* Listen for save event
*/
protected static function boot()
{
parent::boot();
static::saving(function($model)
{
return $model->validate();
});
}
/**
* Validates current attributes against rules
*/
public function validate()
{
$v = $this->validator->make($this->attributes, static::$rules);
if ($v->passes())
{
return true;
}
$this->setErrors($v->messages());
return false;
}
/**
* Set error message bag
*
* #var Illuminate\Support\MessageBag
*/
protected function setErrors($errors)
{
$this->errors = $errors;
}
/**
* Retrieve error message bag
*/
public function getErrors()
{
return $this->errors;
}
/**
* Inverse of wasSaved
*/
public function hasErrors()
{
return ! empty($this->errors);
}
}
Then, adjust your Post model.
Also, you need to define validation rules for this model.
app/models/Post.php
class Post extends Model
{
// validation rules
protected static $rules = [
'name' => 'required'
];
}
Controller method
Thanks to Model class, Post model is automaticaly validated on every call to save() method
public function store()
{
$post = new Post(Input::all());
if ($post->save())
{
return Redirect::route('posts.index');
}
return Redirect::back()->withInput()->withErrors($post->getErrors());
}
This answer is strongly based on Jeffrey Way's Laravel Model Validation package for Laravel 4.
All credits to this man!
How to override Model::save() in Laravel 4.1
public function save(array $options = array())
{
parent::save($options);
}
If you want to overwrite the save() method, it must be identical to the save() method in Model:
<?php
public function save(array $options = array()) {}
And; you can also hook in the save() call with the Model Events:
http://laravel.com/docs/eloquent#model-events