I've just migrated a project that was working great on my localhost to a shared hosting and my components suddently are not getting the methods that i gave them and i'm getting errors in my views like so :
Undefined variable: CatPromo
this is my Component :
<?php
namespace App\View\Components;
use Illuminate\View\Component;
use App\Categories;
class promo extends Component
{
/**
* Create a new component instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Get the view / contents that represent the component.
*
* #return \Illuminate\View\View|string
*/
public function render()
{
return view('components.promo');
}
public function CatPromo()
{
$Categories = Categories::all();
return $Categories;
}
}
Update : I removed the App\View\Components\promo.php to see if it can help me by throwing an error and it seems that he don't even detect the controller.
The documentation says: You should define the component's required data in its class constructor.
public function __construct($CatPromo)
{
// use as variable
$this->CatPromo = $CatPromo;
}
// use as method
public function CatPromo()
{
$Categories = Categories::all();
return $Categories;
}
And in blade template:
#foreach($CatPromo() as $key => $Categorie)
Related
I am finding a way to somewhat fire an event after the Eloquent has finished creating.
Here's my code in Branch model:
class Branch extends Model
{
//some code here
public static function boot() {
parent::boot();
self::created(function (HistoryLog $model) {
$model->tag = 'Created';
$model->description = 'This branch was created by '. ucwords(auth()->user()->name());
$model->save();
});
}
}
What I'm trying to do is, I want to create a history_log after branch was created.
But this code returns an error:
Symfony\Component\Debug\Exception\FatalThrowableError : Argument 1 passed to
App\Vehicle::App{closure}() must be an instance of App\HistoryLog, instance of
App\Vehicle given, called in D:\document\My Documents\optodph\vendor\laravel\fr
amework\src\Illuminate\Events\Dispatcher.php on line 347
Can someone point out to me what's wrong with that code? And what's the right way to achieve this?
Laravel way to do this.
Create an Observer:
php artisan make:observer BranchObserver --model=Branch
Add your logic to the Observer:
<?php
namespace App\Observers;
use App\Branch;
class BranchObserver
{
/**
* Handle the Branch "created" event.
*
* #param \App\Branch $branch
* #return void
*/
public function created(Branch $branch)
{
// Add your logic here
}
}
Register it in AppServiceProvider:
<?php
namespace App\Providers;
use App\Branch;
use App\Observers\BranchObserver;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
Branch::observe(BranchObserver::class);
}
}
$model is a new record created. Is an instance of App\Vehicle not a App\HistoryLog.
Working code might look like this:
class Vehicle extends Model
{
//some code here
public static function boot() {
parent::boot();
self::created(function ($model) {
App\HistoryLog::create([...]);
});
}
}
You can also achieve this with Eloquent Observers https://laravel.com/docs/5.8/eloquent#observers
I have make a Trait for UUID. I use a lot of relationschip inside my code. On a relationship you can do find() and findOrFail() but i have write a code for findU() and findUOrFail() but i can't use it inside a relationship. How can i fix it?
Trait:
<?php
namespace App\Modules\Base\Traits;
use Ramsey\Uuid\Uuid;
/**
* Trait Uuids
*
* #package Modules\Core\Traits
*/
trait Uuids
{
/**
* Boot function from laravel.
*/
public static function bootUuids ()
{
static::creating(function ($model) {
$model->uuid = Uuid::uuid4()->toString();
});
}
/**
* #param $uuid
*
* #return mixed
*/
public static function findU ($uuid)
{
return static::where('uuid', '=', $uuid)->first();
}
/**
* #param $uuid
*
* #return mixed
*/
public static function findUOrFail($uuid)
{
$post = static::where('uuid', '=', $uuid)->first();
if( is_null($post) ) {
return abort(404);
} else {
return $post;
}
}
}
Controller:
/**
* Show
*/
public function show(Request $request, $uuid)
{
return responder()->success($request->user()->projects()->findUOrFail($uuid))->respond();
}
Error:
Call to undefined method Illuminate\\Database\\Eloquent\\Relations\\BelongsToMany::findUOrFail()
Assuming you don't need id since you're using uuid
In your migration file you need:
$table->uuid('uuid');
$table->primary('uuid');
In your model:
use Uuids;
protected $primaryKey = 'uuid';
public $incrementing = false;
Or much easier
In your migration file:
$table->uuid('id');
$table->primary('id');
In your model:
use Uuids;
public $incrementing = false;
You don't need to override findOrFail or find
It should help to have the function referenced directly in the model rather than trying to access it directly in a trait. I am assuming that you are including the Uuids trait above in your projects model. If so, try creating a method on the projects model like this:
public function tryFindUOrFail($uuid)
{
return $this->findUOrFail($uuid);
}
Then you would write your show method as:
return responder()->success($request->user()->projects()->tryFindUOrFail($uuid))->respond();
If this doesn't work, you may need to include your method with the $appends array so that it is directly accessible through the relationship.
I am trying to do pushnotification when a new user signup.So I created events called MemberNotificationEvents, when I fired an event event(new MemberNotificationEvent($UserDetails)); on my signUpController flow is completely going but on the MemberNotificationListener a public function handle(MemberNotificationEvent $event) return error that :
Call to a member function send() on string
I put full code of MemberNotificationListener :
<?php
namespace App\Listeners;
use App\Events\MemberNotificationEvent;
use App\Services\PushNotificationService;
use Illuminate\Contracts\Queue\ShouldQueue;
class MemberNotificationListener implements ShouldQueue
{
private $pushNotificationService;
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
$this->pushNotificationService = PushNotificationService::class;
}
private function getMessageBody($username)
{
return "Awesome! Welcome " . $username . " to IDM";
}
/**
* Handle the event.
*
* #param object $event
* #return void
*/
public function handle(MemberNotificationEvent $event)
{
$username = $event->UserDetails->name;
$message = $this->getMessageBody($username);
$this->pushNotificationService->send($event,['body' => $message]); // throw error
}
}
What is the problem in my code?
The problem is with this line:
$this->pushNotificationService = PushNotificationService::class;
When you do SomeClass::class, it means you supply the class name - not the actual class.
Hence, when you later do $this->pushNotificationService->send(...), the push notification service is just the class name and not the service class.
The second part of the problem is that you need an actual object to put in there. Laravel can inject it for you in the constructor, and then you can supply it. Like this:
public function __construct(PushNotificationService $service)
{
$this->pushNotificationService = $service;
}
So I've created an API Resource and in the toArray() method, I've filtered which attributes get returned via query strings. I want to be able to do this for most of my API Resources so it makes sense to move this into a reusable method. What would be the best way of doing this?
I was thinking about extending the base Resource but I'm not sure how I would go about doing that. Or should it be moved into a service class or repository?
My method is below;
public function toArray($request)
{
if($request->fields) {
$fields = [];
$selectedFields = explode(',', $request->fields);
foreach($selectedFields as $field) {
if(isset($this->{$field})) {
$fields[$field] = $this->{$field};
}
}
return $fields;
} else {
return parent::toArray($request);
}
}
Ideally, I would like to do something like...
public function toArray($request)
{
if($request->fields) {
return parent::filterFields($request); // Not sure whether it should be parent::, $this or something else?
} else {
return parent::toArray($request); // Not sure whether it should be parent::, $this or something else?
}
// or event just
return parent::filterFields($request); // Not sure whether it should be parent::, $this or something else?
}
Full Classes:
ProjectResource.php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class ProjectResource extends Resource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request
* #return array
*/
public function toArray($request)
{
dd(parent::filterFields());
// or
dd($this->filterFields());
if($request->fields) {
$fields = [];
$selectedFields = explode(',', $request->fields);
foreach($selectedFields as $field) {
if(isset($this->{$field})) {
$fields[$field] = $this->{$field};
}
}
return $fields;
} else {
return parent::toArray($request);
}
}
}
Test.php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\Resource;
class Test extends Resource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request
* #return array
*/
public function filterFields($request)
{
return 'test';
}
}
Thank you!
If you're extending the class, you can use either parent:: or $this->. The difference being parent will always refer to the parent class, $this will only refer to the parent if the method does not exist on the current class. Therefore, using $this allows extension of methods and properties.
Example:
<?php
class A {
public function test() {
echo 'A';
}
}
class B extends A {
public function test() {
echo 'B';
}
public function callParent(){
parent::test();
}
public function callThis() {
$this->test();
}
}
$b = new B();
$b->callParent(); // Echoes A
$b->callThis(); // Echos B
In your updated class representation, you have both classes extending Resource but ProjectResource will have no idea about the methods in Test. You would need ProjectResource to extend Test, which will also inherit methods from Resource since Test extends Resource (multiple inheritence).
Beyond that, how you implement is going to be opinion based and you have lots of options. You can extend an abstract class, you can use a dedicated filtering class, or you can use a trait.
You can extend the resource
<?php
namespace App\Http\Resources;
use App\Http\Resources\Product as ProductResource;
class ProductQuantity extends ProductResource
{
/**
* Transform the resource into an array.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function toArray($request)
{
$parent = parent::toArray($request);
return array_merge($parent, [
'depotsQuantity' => $this->warehouses->sum('pivot.quantity'),
]);
}
}
Im working on a Laravel 5 app and im trying to set up a ComposerServiceProvider to pass data to a couple of views (im trying now to add it to the layout/app.blade.php).
I did this following the documentation but the data im trying to add is still undefined..
In my config/app.php I added to the providers:
App\Providers\ComposerServiceProvider::class,
On ComposerServiceProvider.php
boot method:
View::composer(['layouts.app'], 'App\ViewComposers\LayoutAppComposer');
On the new created LayoutAppComposer.php
compose(View $view) method:
$metaTitle = 'MetaTitle';
$view->with('metaTitle', $metaTitle)
But When i access the url I still get:
Undefined variable: metaTitle (View: .../resources/views/layouts/app.blade.php)
Am I missing something here??
ServiceProvider
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\View;
class ComposerServiceProvider extends ServiceProvider
{
/**
* Bootstrap the application services.
*
* #return void
*/
public function boot()
{
View::composer(['layouts.app'], 'App\ViewComposers\LayoutAppComposer');
}
/**
* Register the application services.
*
* #return void
*/
public function register()
{
}
}
LayoutAppComposer
<?php
namespace App\ViewComposers;
use Illuminate\Support\Facades\Session;
use Illuminate\View\View;
class LayoutAppComposer {
protected $metaTitle;
public function __construct($metaTitle)
{
$this->metaTitle = $metaTitle;
}
/**
* Bind data to the view.
*
* #param View $view
* #return void
*/
public function compose(View $view) {
$this->metaTitle = 'MetaTitle';
$view->with('metaTitle', $this->metaTitle);
}
}
Try changing:
$metaTitle = 'MetaTitle';
$view->with('metaTitle', $metaTitle)
to
$this->metaTitle = 'metaTitle';
$view->with('metaTitle', $this->metaTitle)
setup $this->metaTitle as a protected class member and assign it in the composer constructor. it may be that $metaTitle is getting garbage collected before you use it since this being resolved at the service provider level.
Since you're registering the composer with your app layout, instead you may need to use the wildcard character in place of app.layout like such:
View::composer('*', function ($view) {
//
});
To resolve $metaTile for the View Composer, try binding in your AppServiceProvider:
$this->app->bind('metaTitle', 'the string i want displayed across all views');