Controller methods in Laravel - php

I was developing codeigniter app for last 2 years and since i started my mvc pattern styling from codeigniter itself, now i'm not a heavy command line user so at first i did had some learning curve with codeigniter but i crossed it and started developing apps with code igniter because we don't need to configure a lot and everything was inside one zip file but now as unfortunately codeigniter is dead and i'm just one person in my team i have to rely on other third party tools which are trusted by others so i decided to switch to laravel, now at starting it was way way tough to migrate from codeigniter because composer and every other stuff, but somehow i crossed that too, but i'm now confused with routing and other stuff and i've tried many tutorials but i'm still not able to see how can i migrate from application where i'm managing students, where they can change email, change phone number updated stuff, in codeigniter it was easy but i don't how to approach this stuff in routing of laravel, now this question sounds way to dumb for community who is already working on laravel but if you see from my point of view it is going to affect my bread and butter. This is how i use to approach in codeigniter
class Student extends CI_Controller{
// usual piece of code of constructor
function update_email()
{
// piece of code to update email
}
}
but now with laravel routing system and all i've no idea how to approach this a resource controller looks like this
<?php
class StudentController extends \BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
//
}
}
now every part is okay but how can i approach things where i've to update only email address or only phone number and stuff

Actually, in your question you have a RESTful controller which could be confusing for you at this time because you are new to Laravel and used CI, so probably you are very so much used with automating URL mapping without route. In this case, for ease, I suggest you to use a plain controller and that is almost same thing that you've did in CI but here in Laravel you have to declare route for every action. So, just create two routes like these:
Rouite::get('something/edit/{id}', array('uses' => 'StudentController#edit', 'as' => 'edit.record'));
Rouite::post('something/update/{id}', array('uses' => 'StudentController#update', 'as' => 'update.record'));
Then create a class/Controller and declare these methods:
class StudentController extends baseController {
// URL: http://example.com/something/edit/10 and it'll listen to GET request
public function edit($id) {
// $record = Load the record from database using the $id/10
// retuen View::make('editform')->with('record', $record);
}
// URL: http://example.com/something/update/10 and it'll listen to POST request
public function update($id) {
// Update the record using the $id/10
}
}
In your form, you need to use http://example.com/something/update/10 as action and you may use route('update.record') or url('something/update/10') to generate the action in the form. Read more on Laravel Documentation.

What you have created (or maybe rather generated) here is called Restful controller. It is some 'standard way' to manage CRUD actions (create/read/update/delete). However there is no need to do it this way. You can add in your controller whatever methods you want and not use Restful Controllers at all. That's your choice.
You can create in your function new method
function updateEmail()
{
// do here whatever you want
}
and in your routes.php file add new route:
Route::match(array('GET', 'POST'), '/changegemail', 'StudentController#updateEmail');
Now you can write your code for this method and it will work.

Related

Laravel query builder macro on loaded models

I have developed a package to enable search method on Eloquent models with JSON.
The engine currently works in a way that a query is appended for supported parameters depending on values provided.
Builder::macro('search', function (Request $request) {
/**
* #var $this Builder
*/
$searcher = new Searcher($this, $request);
$searcher->search();
return $this;
});
Which in turn runs the following:
/**
* Perform the search
*
* #throws Exceptions\SearchException
*/
public function search(): void
{
$this->appendQueries();
Log::info('[Search] SQL: ' . $this->builder->toSql());
}
/**
* Append all queries from registered parameters
*
* #throws Exceptions\SearchException
*/
protected function appendQueries(): void
{
foreach ($this->requestParametersConfig->registered as $parameter) {
$requestParameter = $this->createRequestParameter($parameter);
$requestParameter->appendQuery();
}
}
protected function createRequestParameter($parameter): AbstractParameter
{
return new $parameter($this->request, $this->builder, $this->modelConfig);
}
Request parameters are registered within configuration file and point to request parameter classes to have everything modular.
Now this works great if used on a something like index endpoint or a custom search endpoint, but I would like to extend the functionality to show as well. The issue being here that with route model binding, the model is already loaded when I fetch it.
Let's take relationships for example. I have a request parameter which when used loads relationships on a given model:
www.example.com/api/contacts?relations=(phones)
will load phones relations on Contact model by doing this:
/**
* Append the query to Eloquent builder
* #throws SearchException
*/
public function appendQuery(): void
{
$arguments = $this->getArguments();
$this->builder->with($arguments);
}
But when I do a ->with on already loaded model followed by ->get(), I just get list of all models with loaded relation.
Is there a way to "tap into" already loaded model with query builder, or is it at this point already done deal, and I should pick up the ID on show route instead of resolving it, and then assemble the query?
After a lot of research of Laravel inner workings, what I asked initially isn't possible.
At the point where you call the method to interact with DB in some way, a query builder instance is made and depending on the method you called on the original model, the query is formed. After execution there is nothing to tap into as the object no longer exists.
Also, from the logical point of view, I have concluded that search makes no sense on already loaded models, so I did a concept switch there and disabled the package for already loaded models.

How do you register custom methods like those within Application.php in Laravel

I am wondering how to register custom method within:
Illuminate/Foundation/Application.php
Like:
/**
* Get the current application name.
*
* #return string
*/
public function getName()
{
return $this['config']->get('app.name');
}
Taken from:
/**
* Get the current application locale.
*
* #return string
*/
public function getLocale()
{
return $this['config']->get('app.locale');
}
Where should I put this, instead of vendor file ofc?
Thanks
You maybe able to extend the Illuminate/Foundation/Application.php
example:
<?php
namespace app\Custom;
class Application extends \Illuminate\Foundation\Application
{
}
for more details, please refer this click here .
Note: Adding your code under vendor files, may lost during the composer update command. So its not advisable to actually add your custom codes there.

Symfony Routing not making sense

I'm teaching myself Symfony. And the routing doesn't make any sense.
I have a postController class with a few actions. Originally the crud generator from the command line gave me this;
/**
* Post controller.
*
* #Route("/post")
*/
class PostController extends Controller
{
/**
* Lists all Post entities.
*
* #Route("/", name="post_index")
* #Method("GET")
*/
public function indexAction()
{
//
}
//
}
What I want to achieve is to remove the #Route from the class itself. Thus I want my indexAction to be the the homepage, and all other actions in my class to still start with /post. For example, this is what I want;
class PostController extends Controller
{
/**
* Lists all Post entities.
*
* #Route("/", name="homepage")
* #Method("GET")
*/
public function indexAction()
{
//
}
/**
* Finds and displays a Post entity.
*
* #Route("post/{id}", name="post_show")
* #Method("GET")
*/
public function showAction(Post $post)
{
//
}
// what I want for the showAction should count for all other Actions as well
}
When I make the change I get an error;
No route found for "GET /post/"
Can somebody please explain to me what I'm doing wrong and how to fix this. I don't think it is something major, it's probably something small that I just don't see. I want to make that indexAction my main action, the action when the website opens after a user logged in. Thank you
Your route specification requires {id} parameter which is obligatory so there's no "GET /post/" route indeed. You need to do one of the following
Pass id value and access /post/1 for example
Remove {id} from route specification and then you can access /post/
Pass default value for id so you can access both /post/ and /post/1. To do that your route specification should look like #Route("post/{id}", name="post_show", defaults={"id" = 1})
No route found for "/post/" is correct
because there is no route "/post/"
in your example theres only "/" and "/post/{id}"
so it makes perfect sense, i prefer to use the yml notation and prefixes so its not bound to a class
check the "YAML" tabs in the DOCS

how to create a controller in laravel

I am new to laravel and creating my first controller in this , i have created a file in directory app/controllers/ContactController.php and the code is
class ContactController extends BaseController {
/**
* Display a listing of the resource.
*
* #return Response
*/
public function index()
{
//
echo "hieeeeeeeeeeeeeeeee";
}
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #return Response
*/
public function store()
{
//
}
/**
* Display the specified resource.
*
* #param int $id
* #return Response
*/
public function show($id)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param int $id
* #return Response
*/
public function update($id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return Response
*/
public function destroy($id)
{
//
}
}
but if i hit url http://localhost:8000/contact it is showing me the error We need a map. am i missing something???please help me.
update
i also tried to add Route::get('contact', "contact#index"); in my routes.php.
i setup an user log in and register module through git-hub and it is working perfectly if i hit url http://localhost:8000/user/login
Update
my laravel version is laravel 4
output in console is 39023 Invalid request (Unexpected EOF)
I fully agree with the things #Raviraj Chauhan already pointed out. in addition, i want to add that your file seems to have a typo which can cause this kind of issue:
Rename your controller-class to ContactController and the containing file to ContactController.php (not contactCtroller.php).
Then add a route to your routes.php-file
Route::get("contact", "ContactController#index");
Generally pay attentions to common conventions and codings-practices, since laravel heavyly depends on concepts such as Convention over Configuration.
As Lukas also pointed out it might be smart to think about switching to Laravel 5 if you are just getting startet.
Anyway, let me finish by recommending laracasts, which is how i learned using laravel. It will only take you a couple of hours to dive deeply into the laravel-universe without to much knowledge needed in advance:
Laravel 4 From Scratch
Laravel 5 Funcamentals (no need to go through L4 from Scratch before)
Yes, There is a problem with your route.
If you want to point to a single method from a controller, then you have to specify a fullControllerName#methodName convention.
Fix your route in routes.php as:
Route::get('contact', "contactController#index");
Also please follow good class naming convention while using OOP.
Controller class name shold start with capital letter.
It should contain Controller at end.
So do fix by renaming your controller class name as well as controller file name, and do:
Route::get('contact', "ContactController#index");
And by easy way, do it by command line by running:
php artisan make:controller ContactController

How to add custom debug data to ZendDebugToolbar

I am using the ZendDebugToolbar and it displays fine on the app, however, how do I send custom debug data to it? For example if I want to dump some key session information to it or a simple var_dump ?
I assume you are referring to the ZFDebug.
Since ZFDebug operates as a front-controller plugin that fires only on dispatchLoopShutdown(), it really only has access to variables that are available there, typically long-lived singleton instances from classes like Zend_Registry, Zend_Controller_Front (so you can get the request and response objects), etc. There is really no mechanism for direct communication between internal processes - like models and controllers - and the ZFDebug plugin.
So, for the kind of debugging about which you ask - var_dump() of your own custom variables and introspecting session data, presumably in other parts of system like services, controllers, models, etc - it might be easiest to simply add that data to Zend_Registry and then examine it later in ZFDebug under the Variables tab.
However, if you really want to add something new to the ZFDebug interface itself, then you can use its own internal plugin system to add tabs/panels to its interface.
It looks like you can simply create a class that implements the interface ZFDebug_Controller_Plugin_Debug_Plugin_Interface (link) and then register your custom plugin with the main $debug object during bootstrap.
Something like this:
/**
* See some of the other plugin implementations for examples of what could go into each of
* these methods.
*/
class My_ZFDebug_Controller_Plugin_SomePlugin implements ZFDebug_Controller_Plugin_Debug_Plugin_Interface
{
/**
* Has to return html code for the menu tab
*
* #return string
*/
public function getTab()
{
// #todo
}
/**
* Has to return html code for the content panel
*
* #return string
*/
public function getPanel()
{
// #todo
}
/**
* Has to return a unique identifier for the specific plugin
*
* #return string
*/
public function getIdentifier()
{
// #todo
}
/**
* Return the path to an icon
*
* #return string
*/
public function getIconData()
{
// #todo
}
}
Then in Bootstrap:
protected function _initZFDebug()
{
$autoloader = Zend_Loader_Autoloader::getInstance();
$autoloader->registerNamespace('ZFDebug');
$options = array(
'plugins' => array('Variables',
'Database' => array('adapter' => $db),
'File' => array('basePath' => '/path/to/project'),
'Cache' => array('backend' => $cache->getBackend()),
'Exception')
);
$debug = new ZFDebug_Controller_Plugin_Debug($options);
// register your custom sub-plugin
$debug->registerPlugin(new My_ZFDebug_Controller_Plugin_SomePlugin());
$this->bootstrap('frontController');
$frontController = $this->getResource('frontController');
$frontController->registerPlugin($debug);
}
As usual, you will have to have autoloading in place for the namespace My_ or whatever you use for your custom class.
Remember, the same constraint as before applies: the only data available to your plugins are the long-lived instances that you can statically pull out of the ether; things like Zend_Registry, Zend_Controller_Front (hence request/response), etc.
#vinygarcia87 is the right answer.
Could not select it as the right answer because you typed it as a comment.

Categories