I am working on a laravel app where i have a user(organizer) who post an event ,and other users can comment on this event .
I am trying to make notifications system in laravel 8 between the organizer and the users when commenting on these event !
but i get this error (Call to a member function notify() on null).
This is my class :
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
class NewCommentPosted extends Notification
{
use Queueable;
protected $user;
protected $event;
public function __construct($user, $event)
{
$this->user = $user;
$this->event = $event;
}
public function via($notifiable)
{
return ['database'];
}
public function toArray($notifiable)
{
return [
'user' => $this->user->name,
'eventTitle' => $this->event->title,
'eventId' => $this->event->id
];
}
This is storefunction() in my controller :
namespace App\Http\Controllers;
use App\Models\Event;
use App\Models\Comment;
use App\Notifications\NewCommentPosted;
use Illuminate\Http\Request;
class CommentController extends Controller
{
public function store(Event $event)
{
request()->validate([
'content' => 'required|min:5'
]);
$comment = new Comment();
$comment->content = request('content');
$comment->user_id = auth()->user()->id;
$event->comments()->save($comment);
$event->user->notify(new NewCommentPosted(auth()->user(), $event));
return redirect()->route('events.show', [$event->id, $event->title]);
}
Any help please !!?
Related
Executed:
composer require uploadcare/uploadcare-php
I can find the library in vendor/uploadcare.
Then added to config/app.php:
'providers' => [
App\Providers\UploadcareServiceProvider::class,
]
and
'aliases' => Facade::defaultAliases()->merge([
'Uploadcare' => App\Facades\Uploadcare::class,
])->toArray(),
Then in App/Facades folder, created this file:
<?php
namespace App\Facades;
use Illuminate\Support\Facades\Facade;
class Uploadcare extends Facade {
protected static function getFacadeAccessor(){
return 'uploadcare';
}
}
This file is successfully referenced in config/app.php according to Visual Studio code.
Then in App/Providers I created UploadcareServiceProvider.php file:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Uploadcare\UploadcareConfiguration;
use Uploadcare\Interfaces\ConfigurationInterface;
class UploadcareServiceProvider extends ServiceProvider
{
public function boot()
{
$this->mergeConfigFrom(__DIR__.'/../../config/uploadcare.php', 'uploadcare');
}
public function register()
{
$this->app->bind(ConfigurationInterface::class, function ($app) {
return new UploadcareConfiguration();
});
$this->app->bind(Uploadcare\Api::class, function ($app) {
$config = $app->make(ConfigurationInterface::class);
return new Uploadcare\Api($config);
});
}
}
This file is successfully referenced in config/app.php according to Visual Studio code, it loads config/uploadcare.php which I have with the following (I redacted my public and private key):
<?php
return [
'public_key' => env('my-public-key'),
'private_key' => env('my-private-key'),
];
Then I created a controller to see whether I can successfully load a list of files form Uploadcare:
<?php
namespace App\Http\Controllers;
use Uploadcare\Api;
use App\Facades\Uploadcare;
use App\Uploadcare\UploadcareConfiguration;
use Uploadcare\Interfaces\ConfigurationInterface;
class UploadcareController extends Controller
{
public function index()
{
$api = Uploadcare::Api(config('uploadcare.public_key'), config('uploadcare.public_secret'));
$files = $api->files()->all();
return $files;
}
}
I call the controller using this route:
Route::get('/uploadcare', [UploadcareController::class, 'index']);
When visiting example.com/uploadcare I get the following error:
Target class [uploadcare] does not exist.
When I change the code in the controller to the following, I get the same error:
$files = Uploadcare::File()->getFileList();
When I hover Uploadcare in Visual Studio it successfully references the Facade.
this is my Auth Service Provider :
<?php
namespace App\Providers;
use App\Models\Profile;
use App\Policies\ProfilePolicy;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use RequestManager\Http\Models\RequestState;
use RequestManager\Policies\RequestStatePolicy;
class AuthServiceProvider extends ServiceProvider
{
protected $policies = [
Profile::class=>ProfilePolicy::class,
RequestState::class=>RequestStatePolicy::class,
];
public function boot()
{
$this->registerPolicies();
}
}
this is my policy array :
array:2 [
"App\Models\Profile" => "App\Policies\ProfilePolicy"
"RequestManager\Http\Models\RequestState" => "RequestManager\Policies\RequestStatePolicy"
]
I have a policy that is in its own module folder with this structure :
this is my controller :
public function showDepartmentRequests($id)//id = department id
{
$request=RequestState::where('department_id',$id)->get();
dd(\Gate::forUser(User::find(2))->allows('view',$request));
}
and this is my policy :
<?php
namespace RequestManager\Policies;
use RequestManager\Http\Models\RequestState;
use App\Models\User;
use Illuminate\Auth\Access\HandlesAuthorization;
class RequestStatePolicy
{
use HandlesAuthorization;
public function view(User $user, RequestState $requestState)
{
dd("test view policy");
}
}
Nothing is printed when I call the gate!
Is this error because I have to register a policy within a specific auth service Provider
other than the app\AuthServiceProvider?
I can use only one middleware at a time..inside a constructor..I want to use if else condition inside constructor or two middleware.
I can use only one middleware inside constructor & if else condition also not working
I want only one function work or use according to middleware.I have two seprate table for authentication
Following middleware pointing to diffrent table
$this->middleware('auth:admin') - admins
$this->middleware('auth')- user
Example are follows
If else
class HRJob extends Controller
{
public function __construct()
{
if(Auth::guard('admin'))
{
$this->middleware('auth:admin');
}
else
{
$this->middleware('auth');
}
}
public function userdetails()
{
dd(Auth::user());
}
}
Two middleware
class HRJob extends Controller
{
public function __construct()
{
$this->middleware('auth:admin');
$this->middleware('auth');
}
public function userdetails()
{
dd(Auth::user());
}
}
You can try like this in the controller
class UserController extends Controller
{
/**
* Instantiate a new UserController instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log', ['only' => [
'fooAction',
'barAction',
]]);
$this->middleware('subscribed', ['except' => [
'fooAction',
'barAction',
]]);
}
}
Also you can use Middleware groups
/**
* The application's route middleware groups.
*
* #var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
],
'api' => [
'throttle:60,1',
'auth:api',
],
];
More: https://laravel.com/docs/master/middleware
Let's say that I had the following API set up:
Controller:
<?php
namespace app\modules\v1\controllers;
use yii;
class ResourceController extends \yii\rest\ActiveController
{
public $modelClass = 'app\modules\v1\models\Resource';
}
Model:
use yii;
class Resource extends \yii\db\ActiveRecord
{
public static function tableName()
{
return 'ResourceTable';
}
public function fields()
{
return [
'id' => 'ResourceID',
'title' => 'ResourceTitle',
];
}
}
where my table only has the two columns, ResourceID and Title.
When I try a GET request on the API, it works fine and returns the list of resources (or single resource in the case of resource/{id}) with the aliased field names. But when I try to POST to create a resource, I want to use the aliased field names (e.g. title instead of ResourceTitle). The problem is that the default CreateAction supplied by Yii does $model->load(), which looks for the field names in the table. If I use the aliased names then it returns an error. If I use the table field names, it works fine.
So my question is, is there a way to expose resource attributes to the end user where the field names (using the fields() function) are the same for reading and creating? If possible, I'd like to avoid writing my own CreateAction.
It's necessary to add rules for new virtual properties, if you want to $model-load() save parameters to them
class OrganizationBranch extends BaseOrganization{
public function rules()
{
return array_replace_recursive(parent::rules(),
[
[['organizationId', 'cityId'], 'safe'],
]);
}
public function fields() {
return ['id',
'cityId' => 'city_id',
'organizationId' => 'organization_id',
'address',
'phoneNumbers' => 'phone_numbers',
'schedule',
'latitude',
'longitude',
];
}
public function extraFields() {
return ['branchType', 'city'];
}
public function getOrganizationId() {
return $this->organization_id;
}
public function setOrganizationId($val) {
$this->organization_id = $val;
}
public function getCityId() {
return $this->city_id;
}
public function setCityId($val) {
$this->city_id = $val;
}
}
You can create getters/setters for alias.
public function getTitle(){ return $this->ResourceTitle; }
public function setTitle($val){ $this->ResourceTitle = $val ; }
How do you implement interface for external package in Laravel? Say, I want to use Mashape/Unirest API to get analyse of text, but in future I would like to switch to other API provider and do not change to much in code.
interface AnalyzerInterface {
public function analyze(); //or send()?
}
class UnirestAnalyzer implements AnalyzerInterface {
function __constructor(Unirest unirest){
//this->...
}
function analyze($text, $lang) {
Unirest::post(.. getConfig() )
}
//some private methods to process data
}
And where to put that files interfece and UnirestAnalyzer? Make special folder for them, add to composer? Add namespace?
This is how I would go to Interface and Implement something like this:
interface AnalyzerInterface {
public function analyze();
public function setConfig($name, $value);
}
class UnirestAnalyzer implements AnalyzerInterface {
private $unirest;
private $config = [];
public function __construct(Unirest unirest)
{
$this->unirest = $unirest;
}
public function analyze($text, $lang)
{
$this->unirest->post($this->config['var']);
}
public function setConfig($name, $value)
{
$this->config[$name] = $value;
}
//some private methods to process data
}
class Analyser {
private $analizer;
public function __construct(AnalyzerInterface analyzer)
{
$this->analyzer = $analyzer;
$this->analyzer->setConfig('var', Config::get('var'));
}
public function analyze()
{
return $this->analyzer->analyze();
}
}
And you must bind it on Laravel:
App::bind('AnalyzerInterface', 'UnirestAnalyzer');