Laravel call controller action from other controller - laravel

I have a post model, a user model, and a point model.
Whenever a user posts a new post, they get a point added (new row in points table).
I have controllers setup for each of those models.
Should/how can I call the PointsController#store from the PostsController#store after adding the post?
Or is this the wrong way to go about it?
Full code on GitHub

Consider using a modal.
For instance, in your PointsController:
public function store() {
// your code
User::addPoint(); // this is responsible for adding the point
}
And in your PostsController
public function store() {
// your code
User::addPoint(); // call this again
}
This way, you have a model responsible for updating the post.

Option1: using models
In PostController
public function store(Request $request){
\Auth::user()->post()->create($request->all());
\Auth::user()->points()->create['point'=> 1]; // add your columns here
}
In Point model
protected $fillable = ['point']; //add here list of columns you want to use on \Auth::user()->points->create['point'=> 1];
Option2: use an observer
create an observer class like here. I would make an Observers folder in app/
https://laravel.com/docs/5.5/eloquent#observers
Call it PostObserver
in PostObserver in create method:
public function created(Post $post)
{
$post->user()->points()->create['point'=> 1]; // [column1=>value1, column2=>value2]
}
In Point model
protected $fillable = ['point']; //add here list of columns you want to use on \Auth::user()->points->create['point'=> 1];
In AppServiceProvider in method boot add
public function boot()
{
Post::observe(PostObserver::class);
}
Don't forget to add the correct namespaces and then add use Observers\PostObserver in AppServiceProvider

Related

Getting the database data to front view in laravel?

As it is quite easy to get data from database in admin panel,but the case is that how can i get/view those data to front view , front view contains the data from several table. Could you please help me ? How can i manage those front pages easily ?
There are a lot of ways, but this is what I normally do.
Use a separate controller method (say index() HomeController) for the frontpage, and create an array of all the variables with the data from database and pass it on to the page. Let's say our homepage has some slider images, some blog posts, and and our team section, then your HomeController would look something like this:
class HomeController extends Controller
{
public function index()
{
$data = []; //your empty array
$data['sliders'] = Slider::all(); //data from sliders table
$data['posts'] = Post::all(); //data from posts table
$data['teams'] = Team::all(); //data from teams table
return view('frontend.index',compact('data'));
}
Now you can access all these in your frontend blade (here index.blade.php) as such:
#foreach($data['teams'] as $key=> $value)
//your loop code
#endforeach
Hope this helps.
In the wonderfull world of laravel this is super easy. But first let me dive a into the structure of laravel a bit.
It all begins with the controller. In Laravel, Controllers a re meant to group assiociated request handling logic within a single class. A basic resource controller would look like this:
class DomainController extends Controller
{
public function index(){} // list domains
public function create(){} // show create form
public function store(Request $request){ } // handle the form POST
public function show($id){} // show a single domain
public function edit($id){} // show edit page
public function update(Request $request, $id){} // handle show edit page POST
public function destroy($id){} // delete a domain
}
Now how can you return the data to the view?
Let's say we want to generate a list of all users using the index function from the controller.
public function index()
{
$users = User::all();
return view('users.index', compact('users'));
}
With this return statement we will get a view and in that view we will have the $users variable available because of the use of the comapct function.
Now if we want to show a simple list:
#foreach($users as $user)
<li>{{$user->name}}</li>
<li>{{$user->age}}</li>
#endforeach

Laravel: Accessing model attributes in the constructor method

How to use __construct on laravel eloquent and get attributes. I tired:
public function __construct() {
parent::__construct();
dd($this->attributes);
}
My code return null. But on abstract class Model filled all attributes:
public function __construct(array $attributes = [])
{
$this->bootIfNotBooted();
$this->initializeTraits();
$this->syncOriginal();
$this->fill($attributes);
}
It's possible get access to model attributes in the constructor method?
Try with accessors.
https://laravel.com/docs/5.8/eloquent-mutators#accessors-and-mutators
Define it like:
public function getFirstNameAttribute($value)
{
return ucfirst($value);
}
And use $this->first_namesomething like this.
I tested this locally by updating the constructor like this:
public function __construct(array $attributes = []) {
parent::__construct($attributes);
dd($this->getAttributes());
}
However, I've discovered that when fetching the object from the database, its attributes are not filled in the constructor, and therefore it's not possible to access them there.
What you can do is access the attributes after the object has been initialized:
$post = Post::find(1);
dump($post->getAttributes());
Not sure if that helps, but it is what it is.
Maybe Events or Observers can help you with what you need:
https://laravel.com/docs/5.8/eloquent#events
https://laravel.com/docs/5.8/eloquent#observers
It's impossible in constructor, because attributes list is empty.
But you can use Events and boot() method of model to achieve desired result:
class MyModel extends Model{
public static function boot(){
parent::boot();
self::retrieved(function ($model) {# Called after data loaded from db
dd($this->attributes); # now attributes was filled
});
}
}
Read more about another events here:
https://www.itsolutionstuff.com/post/laravel-model-events-tutorialexample.html

Laravel How not to Rewrite the Same code again

I have a model, called Tours and controller ToursController which uses restful methods (index, show, store, edit, update etc).
Now I have this code:
$names = request()->get('names');
$lastnames = request()->get('lastnames');
$hotels = request()->get('hotel');
both in Store and Update. So i duplicate the same code twice. And this is only one exmaple of duplicated code.
I want to create a function "getEverythingFromRequest()"
which I can use in both Store and Update methods. Something like:
public function store (Request $request) {
getEverythingFromRequest();
dd($names[3];
}
public function store (Request $request) {
getEverythingFromRequest();
dd($hotels[2];
}
How can I do it? Globally, how can I avoid re-writing the same code in Controller?
There are a bunch of ways to solve this. One way would be to create a repo that extracts the arrays from your request. (I updated my code to use injection).
Controller
public function store (GuestsRepository $repo, Request $request) {
dd($repo->names);
}
Repository
<?php
namespace App;
class GuestsRepository
{
public $names;
public $lastnames;
public $hotels;
public function __construct(){
$this->names = request()->get('names');
$this->lastnames = request()->get('lastnames');
$this->hotels = request()->get('hotel');
}
}

How to create custom model events laravel 5.1?

I want to create a custom model event in laravel 5.1.
For e.x. when an Articles category is updated i want to make an event and listen to it.
$article = Article::find($id);
$article->category_id = $request->input('category_id');
// fire an event here
You should use Eloquent Events (do not confuse with Laravel Events).
public function boot()
{
Article::updated(function ($user) {
// do some stuff here
});
}
You would want to look into Observers to make this more reusable and single-responsible, though a starting point would be something alike:
public function boot()
{
self::updated(function ($model) {
if (array_key_exists('category_id', $model->getDirty())) {
// Log things here
}
});
}
Laravel will populate a 'dirty' array which contains modified fields. You can detect when a certain field has changed using this.
You also have:
$model->getOriginal('field_name') // for this field value (originally)
$model->getOriginal() // for all original field values
You can use Attribute Events to fire an event when the category_id attribute changes:
class Article extends Model
{
protected $dispatchesEvents = [
'category_id:*' => ArticleCategoryChanged::class,
];
}

How to define a relationship that touches grandparents in eloquent

In Laravel, I would like to define a grandparent type eloquent relationship so that I can have the grandchild touch the grandparent when it is added or updated (for instance if it brings the grandparent a very nice birthday card). Say I have a hierarchy like Collection > post > comment.
--Comment--
protected $touches = array('post', 'collection');
public function post()
{
return $this->belongsTo('Post');
}
public function order()
{
// not working
// return $this->post->collection();
// not working
// return $this->belongsTo('Post')->belongsTo('Collection');
}
--Post--
public function collection()
{
return $this->belongsTo('Collection');
}
I want the update function in the Collection to run when a Comment is added. How can I set that up?
I'm using Laravel 4.1
I want the update function in the Collection to run when a Comment is
added.
I'm a bit confused about the update function but...
You can register an event handler for that, for example, add this in your Comment model:
class Comment extends Eloquent {
public static function boot()
{
parent::boot();
static::created(function($comment)
{
// $comment is the current Comment instance
});
}
}
So, whenever any Comment will be created the event handler (anonymous function) will run so you may do something in that function. Read more on Laravel Website.

Resources