Looks simple (and maybe) but I need pass a received variable in a function to another function. Here's my code:
PD: I using Laravel Eloquent's Scopes
class myParentModel extends Model {
public function scopeMyScope($query, $VAR_I_WANT_TO_PASS=[]) {
return $query->with('model'])->whereHas('model', function($q, $VAR_I_WANT_TO_PASS=[]) {
$q->where('colum1',$VAR_I_WANT_TO_PASS[0])->where('colum2',$VAR_I_WANT_TO_PASS[1])->where('colum3',$VAR_I_WANT_TO_PASS[2]);
})->take(10);
}
}
and I want to do this:
$result = myParentModel::myScope([3,1,6])->get();
I resolve this using use:
class myParentModel extends Model {
public function scopeMyScope($query, $VAR_I_WANT_TO_PASS) {
return $query->with('model'])->whereHas('model', function($q) use ($VAR_I_WANT_TO_PASS) {
$q->where('colum1',$VAR_I_WANT_TO_PASS[0])->where('colum2',$VAR_I_WANT_TO_PASS[1])->where('colum3',$VAR_I_WANT_TO_PASS[2]);
})->take(10);
}
}
Related
I am new to Laravel. I have some functions in PaymentController. I want to call those functions from SmartpaySController. Here is the function which is available in PaymentController. Help me to call that function by staying in SmartpaySController.
public function getPaymentFailed($paymentId) {
$transactionData = $this->paymentRepo->find($paymentId);
if($transactionData) {
$data['quote'] = $this->quoteRepo->getQuoteById($transactionData->quote_id);
$data['metaTitle'] = 'Payment failed';
$data['returnMessage'] = $transactionData->return_message;
return view('payment::payment.quote_payment_failed', $data);
}
}
Thank you.
Instead of calling controller methods, the better practice is that you can create traits like: app/Traits and extend in controller
//trait
trait traitName {
public function getData() {
// .....
}
}
//Controller
class ControlelrName extends Controller {
use TraitName;
}
I recomend you to not call functions from one controller to another.
Make Helpers, Resources or implement same feature in other way
Never use controllers as object
But if you want to do it anyway you can use:
SomeController.php
class SomeController extend Controller {
public function someFunction(Request $request) {
// Here Some Code
}
}
YourController.php
use SomeController;
...
public function getPaymentFailed(Request $request, $paymentId) {
$controller_data = (new SomeController)->someFunction($request);
$transactionData = $this->paymentRepo->find($paymentId);
if($transactionData) {
$data['quote'] = $this->quoteRepo->getQuoteById($transactionData->quote_id);
$data['metaTitle'] = 'Payment failed';
$data['returnMessage'] = $transactionData->return_message;
return view('payment::payment.quote_payment_failed', $data);
}
}
Change:
public function getPaymentFailed($paymentId)
to:
public static function getPaymentFailed($paymentId)
This will make it staticly available in your SmartpaySController by doing:
PaymentController::getPaymentFailed($paymentId);
You can make use of Real-Time Facades
Using real-time facades, you may treat any class in your application
as if it were a facade.
To generate a real-time facade, prefix the namespace of the imported
class with Facades:
//...
use use Facades\App\Http\Controllers\SomeController;
//...
return SomeController::getPaymentFailed($request, $paymentId);
I have separate validate_date functions in controller1.php, controller2.php, and controller3.php. I want to create a global function in DateTimeHelper.php to validate dates instead of creating a function in each controller for this functionality. I am using Laravel in the backend
Controller1:
private function validate_date($date)
{
$split_date = explode('/', $date);
if (count($split_date) == 3) {
return checkdate($split_date [0], $split_date [1], $split_date [2]);
}
return false;
}
Controller2 && controller 3:
private function validate_date($date)
{
if ($this->check_field($date) && $date !== 'Invalid date') {
return true;
}
return false;
}
My problem is that I am using different functions in different controllers, I need a global function to validate dates instead of creating a function in each controller for this functionality.
The following method will probably do what you're looking for:
Create a new file called DateTimeHelper.php inside a (new) Helpers folder. The final path will be app\Helpers\DateTimeHelper.php.
The content of DateTimeHelper.php will look like:
<?php
namespace App\Helpers;
class DateTimeHelper {
public function validate()
{
}
public function checkField()
{
}
}
Now edit the controllers where you want to use the class, add a procted property $dateTimeHelper and use Laravel's Automatic Injection like this:
<?php
namespace App\Http\Controllers;
use App\Helpers\DateTimeHelper;
class UserController extends Controller
{
protected $dateTimeHelper;
/**
* Create a new controller instance.
*
* #param DateTimeHelper $dateTimeHelper
* #return void
*/
public function __construct(DateTimeHelper $dateTimeHelper)
{
$this->dateTimeHelper = $dateTimeHelper;
}
public function show($date)
{
return $this->dateTimeHelper->validate($date);
}
}
Hopefully this should solve the problem, however, I'd recommend to look into Laravel validation.
How about a Service Class instead of helper function and put all possible date validation from the system into this Service Class?
Through this query I find a element in a database by value and take the id:
Model::where($table,'=',$value)->first()->id;
But I need to create a method, because I use this code with other models; a possible example:
public function getId($model,$table,$value) {
...
}
How can I do?
Thanks!
Method
public function getId($model, $table, $value) {
return $model::where($table, $value)->first()->id;
}
Usage
$id = getId('App\User', 'name', 'John Doe');
From your code, it looks like you have this as a class method. Instead, you could create this as a global helper so you can access it anywhere.
I would create a Trait
<?php
namespace App\Models\Traits;
trait GetIdByNameTrait
{
public function scopeGetIdByName($query, $name)
{
return $query->where('name', $name)->first()->id;
}
}
The models should use it:
use Traits\GetIdByNameTrait;
Then you can use this everywhere;
$id = Model::getIdByName($value);
I have a Product model
class Product extends Model
{
...
public function prices()
{
return $this->hasMany('App\Price');
}
...
}
I want to add a function which will return the lowest price, and in controller I can get the value using:
Product::find(1)->lowest;
I added this in Product model:
public function lowest()
{
return $this->prices->min('price');
}
but I got an error saying:
Relationship method must return an object of type Illuminate\Database\Eloquent\Relations\Relation
And if I use Product::find(1)->lowest();, it will work. Is it possible to get Product::find(1)->lowest; to work?
Any help would be appreciated.
When you try to access a function in the model as a variable, laravel assumes you're trying to retrieve a related model. They call them dynamic properties. What you need instead is a custom attribute.
Before Laravel 9
Laravel 6 docs: https://laravel.com/docs/6.x/eloquent-mutators
add following method to your model:
public function getLowestAttribute()
{
//do whatever you want to do
return 'lowest price';
}
Now you should be able to access it like this:
Product::find(1)->lowest;
EDIT: New in Laravel 9
Laravel 9 offers a new way of dealing with attributes:
Docs: https://laravel.com/docs/9.x/eloquent-mutators#accessors-and-mutators
// use Illuminate\Database\Eloquent\Casts\Attribute;
public function lowest(): Attribute
{
return new Attribute(
get: function( $originalValue ){
//do whatever you want to do
//return $modifiedValue;
});
/**
* Or alternatively:-
*
* return Attribute::get( function( $originalValue ){
* // do whatever you want to do
* // return $modifiedValue;
* });
*/
}
Use Eloquent accessors
public function getLowestAttribute()
{
return $this->prices->min('price');
}
Then
$product->lowest;
you can use above methods or use following method to add a function direct into existing model:
class Company extends Model
{
protected $table = 'companies';
// get detail by id
static function detail($id)
{
return self::find($id)->toArray();
}
// get list by condition
static function list($name = '')
{
if ( !empty($name) ) return self::where('name', 'LIKE', $name)->get()->toArray();
else return self::all()->toArray();
}
}
Or use Illuminate\Support\Facades\DB; inside your function. Hope this help others.
why you just dont do this? i know , it's not what you asked for specificallyand it migh be a bad practice sometimes. but in your case i guess it's good.
$product = Product::with(['prices' => function ($query) {
$query->min('price');
}])->find($id);
change follow code
public function lowest()
{
return $this->prices->min('price');
}
to
// add get as prefix and add posfix Attribute and make camel case function
public function getLowestAttribute()
{
return $this->prices->min('price');
}
Is it possible to pass, somehow, a parameter to a relationship function?
I have currently the following:
public function achievements()
{
return $this->belongsToMany('Achievable', 'user_achievements')->withPivot('value', 'unlocked_at')->orderBy('pivot_unlocked_at', 'desc');
}
The problem is that, in some cases, it does not fetch the unlocked_at column and it returns an error.
I have tried to do something like:
public function achievements($orderBy = true)
{
$result = $this->belongsToMany (...)
if($orderBy) return $result->orderBy(...)
return $result;
}
And call it as:
$member->achievements(false)->(...)
But this does not work. Is there a way to pass parameters into that function or any way to check if the pivot_unlocked_at is being used?
Well what I've did was just adding new attribute to my model and then add the my condition to that attirbute,simply did this.
Class Foo extends Eloquent {
protected $strSlug;
public function Relations(){
return $this->belongsTo('Relation','relation_id')->whereSlug($this->strSlug);
}
}
Class FooController extends BaseController {
private $objFoo;
public function __construct(Foo $foo){
$this->objFoo = $foo
}
public function getPage($strSlug){
$this->objFoo->strSlug = $strSlug;
$arrData = Foo::with('Relations')->get();
//some other stuff,page render,etc....
}
}
You can simply create a scope and then when necessary add it to a builder instance.
Example:
User.php
public function achievements()
{
return $this->hasMany(Achievement::class);
}
Achievement.php
public function scopeOrdered(Builder $builder)
{
return $builder->orderBy(conditions);
}
then when using:
//returns unordered collection
$user->achievements()->get();
//returns ordered collection
$user->achievements()->ordered()->get();
You can read more about scopes at Eloquent documentation.
You can do more simple, and secure:
When you call the relation function with the parentesis Laravel will return just the query, you will need to add the get() or first() to retrieve the results
public function achievements($orderBy = true)
{
if($orderBy)
$this->belongsToMany(...)->orderBy(...)->get();
else
return $this->belongsToMany(...)->get();
}
And then you can call it like:
$member->achievements(false);
Works for the latest version of Laravel.
Had to solve this another was as on Laravel 5.3 none of the other solutions worked for me. Here goes:
Instantiate a model:
$foo = new Foo();
Set the new attribute
$foo->setAttribute('orderBy',true);
Then use the setModel method when querying the data
Foo::setModel($foo)->where(...)
This will all you to access the attribute from the relations method
public function achievements()
{
if($this->orderBy)
$this->belongsToMany(...)->orderBy(...)->get();
else
return $this->belongsToMany(...)->get();
}