Can i create a function inside a function in Codeigniter? - codeigniter

If I can create a function then how do I call it from another function in the same controller,
I have created a function which gets data from a form like to,cc,bcc, subject etc .They are part of a form and another form which gets attachments from the function in which I get attachments. I want to call a function which is getting the other details so i can send a email.
function emaildata()
{
//here it fetches details like subject message
function Sendmail($attachments)
{
//send your mail
}
}
function getattachments()
{
//get attachments here
sendmail($attachments);
}

You can call function from same controller! as its Same class.
But try to make it non public function so it won't be accessible form the website ( ex : use _ {underscore} in the beginning of the method name)
Reference here : http://ellislab.com/codeigniter/user-guide/general/controllers.html#private

You can define private controller function like this (private function names must start with underscore):
private function _get_details()
{
// some code
}
it will not be accessible through url, but you can invoke it like this:
function send_mail()
{
//do something
$this->_get_details();
// and we called the other method here!
}
You can restructure your code like this:
public function emaildata()
{
//here it fetches details like subject message
$emaildata->subject = "..";
//get attachments
$attachments = $this->_getattachments();
$this->_sendmail($emaildata,$attachments);
}
private function _getattachments() {
//get attachments here
}
private function _sendmail($emaildata,$attachments)
{
//send your mail
}

Related

How to use model class to edit , destroy and get single value in laravel 8 resource controller?

I want to develop an API with Laravel 8 with resource controller.
Previously we used id parameter to edit, delete and get single value from the database. But now, here is given model class as a parameter in show, edit, update and destroy method.
How can I use this model class to perform crud operations without id parameter?
I know I’m on a misconception and I want to get a clear idea.
public function show(Food $food)
{
//
}
public function edit(Food $food)
{
//
}
public function update(Request $request, Food $food)
{
//
}
public function destroy(Food $food)
{
//
}
This is just a better way of retrieving your data.
Instead of writing:
public function show($id)
{
echo $id; // 12
$food = Food::find($id); // your food instance with id 12
echo $food->id; //12
}
You write:
public function show(Food $food)
{
$food; // your food instance with id 12
echo $food->id; //12
}
Laravel will match the parameter name of your route with the argument name in your controller method declaration and will automatically gives you the correct Food instance.
Your routes should looks like this:
Route::get('foods/{food}', [FoodController::class, 'show'])->name('foods.show');
// for each verbs (index, show, update...)
// the "food" parameter will be internally mapped
// to the $food argument inside your controller methods declaration
// or even simpler:
Route::resource('foods', FoodController::class);
// which will declare all routes for this resource
This is called implicit model binding. The documentation on this topic can be find here: https://laravel.com/docs/8.x/routing#implicit-binding

Laravel Route Model Binding Reusability

I'm creating a like feature for my application where users can like posts, events, products etc.
I have a LikeController and a Trait which handles the like functionality
public function store(Post $post)
{
$post->like();
return back();
}
The code above is to like a post
I don't want to duplicate code and create separate functions to perfrom the same exact thing on events or products and I was wondering how to perform route model binding and get the application to just execute the one function, passing model information depending on what is being liked post, event or product.
The following code works fine but does not implement the DRY principle
public function store(Post $post)
{
$post->like();
return back();
}
public function store_event(Event $event)
{
$event->like();
return back();
}
The followinf is the trait
trait LikeTrait
{
public function getLikesCountAtrribute()
{
return $this->likes->count();
}
public function like()
{
if (!$this->likes()->where(['user_id' => auth()->id()])->exists()) {
$this->likes()->create(['user_id' => auth()->id()]);
}
}
public function likes()
{
return $this->morphMany(Like::class, 'likeable');
}
public function isLiked()
{
return !!$this->likes->where('user_id', auth()->id())->count();
}
}
My web routes file is as follows
Route::post('post/{post}/likes', 'LikeController#store');
Route::post('event/{event}/likes', 'LikeController#store_event');
So the outcome I want is to call the same method and pass the relevant model.
Thanks in advance
You can have a specific route for such actions, may it be 'actions':
Route::post('actions/like','ActionsController#like')->name('actions.like');
Then in the request you send the object you wish to perform the action on, i personal have it hashed, the hash contains the ID and the class_name (object type) in an stdClass.
That's how i personally do it:
Every Model i have inherits Base Model, which contains hash attribute, which contains
$hash = new stdClass;
$hash->id = $this->id;
$hash->type = get_class($this);
return encrypt($hash);
This will return a string value of what's there, and encrypted, you can have a password for that as well.
Then you let's say you have the like button inside a form or javascript you can do that:
<form action="{{ route('actions.like') }} method="post">
<input type="hidden" name="item" value="{{ $thisViewItem->hash }}">
<button type="submit">Like</button>
</form>
Doing so, when liking an object you send the hashed string as the data, thus getting a request of $request->get('item') containing the object (id and type). then process it in the controller however you like.
If you're sending this through javascript you may want to urlencode that.
then in ActionsController#like you can have something like that:
$item = decrypt($request->get('item'));
# Will result in:
# Item->id = 1;
# Item->type = 'App\Post';
$Type = $Item->type;
# Build the model from variable
# Get the model by $item->id
$Model = (new $Type)->find($item->id);
# Like the model
$Like = $Model->like();
// the rest...
I personally prefer to combine and encrypt the id+type in a string, but you can send the id and type in plain text and have a route named like so:
Route::post('actions/like/{type}/{id}','ActionsController#like');
Then build the model from the Type+ID followed by what you have in trait ($Model->like());
It's all up to you, but i'm trying to hint that if you want to reuse the like action in many places, you may want to start building the logic starting from the action itself(likes, comments) not from the target (posts, events).
The codes i placed in here are written in here and not pasted from what i actually do, I'm trying to get you the concept. You can write it however you prefer.
I don't know whether this is gonna work, but please have a go.
You could try explicit binding. Lets define explicit bindings in the App\Providers\RouteServiceProvider:
public function boot()
{
parent::boot();
Route::model('post', App\Post::class);
Route::model('event', App\Event::class);
}
Then defining the routes:
Route::post('/posts/{post}/likes', 'LikesController#store');
Route::post('/events/{event}/likes', 'LikesController#store');
Finally in the controller:
class LikesController extends Controller
{
public function store($object)
{
$object->like();
}
}

Model function call in a Template

I have model called Page and view called view.blade.php
//this is a model
public function Test()
{
return 'test';
}
//this is the template
<h1>{{$Test}}</h1>
how can I do this? please help me?
As I understood, you want to call model function inside your view? Do it like this:
{{Page::Test()}}
Edit:
If you need to use $this in your function to pass some data for your function (if that was what you were asking in comments below), you can do something like this. First define your static function:
public static function getPages()
{
return [
//some logic (get all pages)
];
}
Now, let's say this function will return multiple pages. If you want to filter them, and to display only one page on your view, you can pass the id of that view as a parameter to a next function which you will then pass to your view:
public function getSinglePage()
{
return self::getPages()[$this->id];
}
Lastly, in order to display the output of that function, use the same method as above, with new function name:
{{Page::getSinglePage()}}

codeigniter child function after submit parent function

In my project I have a controller call load and it has a fuction call search() that has a form, i want to submit this form in a child function of search() like this,,
localhost/ci/index.php/load/search
to
localhost/ci/index.php/load/search/something/
how can i do this after submission a form?
this is my contoller like
class Load extends CI_Controller {
function search() {
$this->load->view('search');
}
function something() {
$this->load->view('something');
}
}
This is not child function something()
You can define routes as per your requirements.
After search function call , you can use redirect() method, that will redirect to your route like 'base_url/controller/search/searchresult/'.
Routes.php
$route['Load/search/searchresult'] = 'Load/something';
Load Controller code :
class Load extends CI_Controller {
function search() {
$this->load->view('search');
// after form submission
redirect('Load/search/searchresult');
}
function something() {
$this->load->view('something');
}
}
This is not a child function of search function so you can call it like
localhost/ci/index.php/load/something/
Add this url to your form action and your form will be submitted to something() function
For clarity: localhost/ci/index.php/load/search/something/ does this...
Enters search() method of Load and provides something as a parameter e.g. search($param = 'something') (this is not correct syntax but just for show).
function search($term = null) {
if (is_null($term)) {
// user hasn't searched
} else {
// user searched for $term e.g. something
}
}
The only way you can achieve what you want is to either use the above somehow to your advantage knowing that /something will have to be the search parameter. Or you can use routing as another answerer suggested.

How to trigger a method in all pages request in Yii?

In the header section of my website I want to show new message. I have a method that fetches new methods and return them. The problem is that header section is in thelayout section and I don't want to repeat one method in all of my controllers.
How to achieve this by not copying the method to all of my controllers? I want to trigger newMessages() method on every page request to gather new messages for logged in user. How to do this the right way?
In your controller overwrite the oOntroller class function beforeAction()
protected function beforeAction($event)
{
$someResult = doSomething()
if ($someResult == $someValue)
{
return true;
}
else
{
return true;
}
}
The return value can be used to stop the request dead in its tracks. So if it returns false, the controller action is not called, and vice versa().
References : http://www.yiiframework.com/doc/api/1.1/CController#beforeAction-detail
You can use import controller in another controller action. something like below
class AnotherController extends Controller
{
public function actionIndex()
{
Yii::import('application.controllers.admin.YourController'); // YourController is another controller in admin controller folder
echo YourController::test(); // test is action in YourController
}
}

Resources