Im having a bit of trouble figuring out how to interact with the database in Laravel.
Im writing a small app, and its come to the point where I need to enter, check and return results.
I have followed the docs to setup authentication and now I can have users log in and out.
So what I want to do is store letters.
I have a table called letters.
A user can write as many letters as they want, their user ID is stored in the letters table in the column called userID
When a user clicks on the 'Letters' navigation item, it takes them to the
Route::get('letters')..........
When it loads the view, if there are no letters in the database I want it to say 'No previous letters' .. if there is some letters in the DB, I just want it to say 'Welcome back'
I cant find how or where to achieve this.
I'm hoping someone can help me out and give me a bit of a hand writing the code as I cant find anything in the docs.
You need to do this in a controller.
Route::get('letters', ['uses' => 'LettersController#index']);
And then in your letters controller
public function index()
{
// Grab letters for the user. You need to be sure that the user is logged in
$letters = Letter::forUser(Auth::user())->get();
$data = [
'letters' => $letters
];
// You will be able to call $letters->count() in your view
return View::make('letters.index', $data);
}
In your letter Model
public function scopeForUser(User $u)
{
return $query->where('user_id', '=', $u->id);
}
Related
I have 2 entities called Match and Roster.
My Match routes are like this
http://localhost:8888/app/public/matches (index)
http://localhost:8888/app/public/matches/14 (show)
In order to view/create the teams for each specific match I added the routes for the match roster like this:
Route::get('/matches/'.'{id}'.'/roster/', [App\Http\Controllers\RosterController::class, 'index']);
Now I need that {id} i have in my URL to pass it to the Controller here:
public function index()
{
return view('roster.index');
}
I need that for a couple of things. First I need to do a search on the Roster table filtering by a column with that value, so I can display only the players that belong to that match.
Second, I need to pass it on to the view so I can use it on my store and update forms. I want to add or remove players from the roster from that same index view.
How can I do that?
#1 You can get the route parameter defined on ur routes via request()->route('parameter_name').
public function index()
{
// get {id} from the route (/matches/{id}/roster)
$id = request()->route('id');
}
#2 You can pass the data object via using return view(file_name, object)
public function index()
{
// get {id} from the route (/matches/{id}/roster)
$id = request()->route('id');
// query what u want to show
// dunno ur models specific things, so just simple example.
$rosters = Roster::where('match_id', '=', $id);
// return view & data
return view('roster.index', $rosters);
}
#3 It can be done not only index but also others (create, store, edit, update)
In addition, STRONGLY RECOMMEND learn Official Tutorial with simple example first.
Like a Blog, Board, etc..
You need to know essentials to build Laravel App.
Most of the time, I prefer named routes.
Route::get('{bundle}/edit', [BundleController::class, 'edit'])->name('bundle.edit');
In controller
public function edit(Bundle $bundle): Response
{
// do your magic here
}
You can call the route by,
route('bundle.edit', $bundle);
I'm new with Laravel (and programming) and I'm a bit confused.
Using the Eloquent ORM I store in the database a list of pets and their info in a pets table with a Pet model and a Pet controller.
I also have a users table with User model.
Then I have an owner_pet table that contains foreing keys to user_id and pet_id, with an OwnerPet model and controller.
I have a view called 'pets' and I want there to be a form and a list of the user pets, only accesible by authenticated users.
I have this route:
Route::get('/pets', [App\Http\Controllers\HomeController::class, 'index'])->name('pets');
There, using the auth middleware it checks the user is logged in and returns the view 'pets', that contains a form to add pets.
public function __construct()
{
$this->middleware('auth');
}
public function index()
{
return view('pets');
}
This works fine.
Then I have a pet controller with an add pet function, I use it with a form in the 'pets' view that calls this route:
Route::post('/add', 'PetController#addPet')->name('add');
When the pet is added I return the 'pets' view with a success message.
return view('pets')->with('success', $success);
This works fine.
Then I have a ownerPets index function where I get all the info I need and store it as $pets and call the 'list' view:
public function index()
{
$ownerPets = OwnerPet::leftjoin('pets', 'pets.id', '=', 'owner_pets.pet_id')
->where('user_id', Auth::user()->id)->paginate(20);
return view('list')->with('pets', $pets);
}
I call the function with this route:
Route::get('/list', 'OwnerPetController#index')->name('list');
This works fine, I can see the list of the user's pets.
But I need to have everything in the same view, and I can only call a single function from the route.
Do I need to make another controller and call all the functions from there and then send all the data to the view? I was told calling a controller from another controller was a bad practice, but I can't think of another way to do this.
Can I maybe make a view that contains the other 2 views? But I don't know how would I get the functions to pass the data to them.
Please I need some advice. Thanks.
This mean that you want a page which have add form at the right side and list of pet with owner information at the left (for example).
so, you just
This Route::get('/list', 'OwnerPetController#index')->name('list'); will return list pet and add from for the same page.
Create another route like Route::post('/add', 'PetController#addPet')->name('add'); (in the same controller or other controller, it up to you) for adding pet.
after you fill up the form and click submit, addPet function must return view('pets');
Hope martch your question.
Thanks
In my application, I have users that are connected to businesses. These businesses have job offers. When a user wants to edit a business' job offer, the url will be like /business/foo/job/bar. When I change the business variable to the name of a different one, like this: /business/other-business/job/bar I still get the job called bar even though it does not belong to the business. I tried to use gates to check if the job offers belong to the business but it didn't work. Below is the code for the edit function which shows the edit page.
public function edit(Business $business, Job $job)
{
return view('dashboard.business.jobs.edit', [
'business' => $business,
'job' => $job,
]);
}
I can add the following code to all the functions but it is not very pretty
if($business->id !== $job->business->id) { return abort(404); }
I was wondering if there is a better solution to this problem.
Well you can choose between
if($business->jobs->contains($job->id)) return redirect()->to("somewhere");
or
if($job->business->is($business)) return redirect()->to("somewhere");
The second one is more efficient because you have to retrive from the database just one record to check if they are correlated, the business record, where the first one instead you have to retrive all the jobs of that business.
Those solution in my opinion are actually very clear, you can literally read them and understand what you are doing.
Also if you want just one line of code, you can do this:
public function edit(Business $business, Job $job)
{
return
$job->business->is($business)
?
view('dashboard.business.jobs.edit', [
'business' => $business,
'job' => $job,
])
:
return redirect()->to("somewhere");
}
I have the following method:
public function destroy($id)
{
$id = \JWTAuth::parseToken()->authenticate();
$offer = Offer::findOrFail($id);
$offer->delete();
return response()->json(["offer" => $offer]);
}
How handle data before deleting? I need to check if user has permit to delete data or not
When you use the authenticate() method, the user model is retrieved so it means the id you have is not an id but a User. Have you checked the documentation of JWT Because first and foremost you have to retrieve the user and this is sufficient:
$user = \JWTAuth::parseToken()->authenticate();
Then if you have a field for example in your users table to tell if the user have the right say admin which can be 1 or 0 then you can do the following:
if($user->admin == 1)
{
$offer = Offer::findOrFail(1); //say id
$offer->delete();
return response()->json(["offer" => $offer]);
}
return response()->json(['error' => 'you dont have the right to delete this'], 403);
Just a little scratch on the idea, but my best advice is to do some searches on how JWT is implemented, I am pretty sure you will find tons of them online.
I would recommend using the Model's delete event:
https://github.com/laravel/framework/blob/5.2/src/Illuminate/Database/Eloquent/Model.php#L1122
and handle it.
This will guarantee that if you use the delete method on a model, you always check permissions.
So im creating a module in the backend, I have a shell module created (items in admin top menu and a page to visit.) basically I want to have an input field that the admin can type a number into then click a button "add", this will insert a row into an existing table in the database.
$connection = Mage::getSingleton('core/resource')->getConnection('core_write');
$connection->beginTransaction();
$fields = array();
$fields['name']= 'andy';
$connection->insert('test', $fields);
$connection->commit();
I have a table called "test" within my database. If I put the above code into my Controller file, it successfully adds a row to the database when i visit the admin page. But i need to allow the user to input the data that is inserted.
Would I have to move that code into the Model and somehow send the input data to the Model and let that do the work? or not. If this is correct could someone point me to a good place to research sending data to models? (if thats even possible)
iv tried lots of tutorials but they are all way to big for what I need, I dont need to display anything, I just need to have an input box and a save button.
EDIT
i have created a file block/Adminhtml/Form/Edit/Form.php which contains the following . . .
class AndyBram_Presbo_Block_Adminhtml_Form_Edit_Form extends Mage_Adminhtml_Block_Widget_Form
{
protected function _prepareForm()
{
$form = new Varien_Data_Form(
array(
'id' => 'edit_form',
'action' => $this->getUrl('*/*/test'),
'method' => 'post',
)
);
$form->setUseContainer(true);
$this->setForm($form);
$fieldset = $form->addFieldset('display', array(
'legend' => 'Display Settings',
'class' => 'fieldset-wide'
));
$fieldset->addField('label', 'text', array(
'name' => 'label',
'label' => 'Label',
));
if (Mage::registry('andybram_presbo')) {
$form->setValues(Mage::registry('andybram_presbo')->getData());
}
return parent::_prepareForm();
}
}
then in my controller i have 2 functions like below . . .
public function indexAction()
{
$this->loadLayout();
$this->_addContent($this->getLayout()->createBlock('presbo/adminhtml_form_edit_form'));
}
public function testAction()
{
echo 'form data here';
$this->loadLayout();
$this->renderLayout();
}
the form is displayed successfully but there is no button to send or say 'do an action'
Further Edit
i have successfully added a submit button to the form that successfully goes to the testAction and echo' "form data here".
how do i then access the data,
iv added the below line
$postData = $this->getRequest()->getPost();
now if i echo $postData, it just puts "array"
if i echo $postData[0] it doesnt put anything just a blank page
any ideas or pointers?
Magento is built as an MVC framework, thus you're right - you need to pass data from controller to the model, and do not do any DB updates directly in a controller's code. The best source for an example is the own Magento code - you can take any controller action, which saves data to DB to see, how it is done. E.g. check app/code/core/Mage/Adminhtml/controllers/NotificationController.php method markAsReadAction().
There you can see, that:
Data is retrieved from the request by calling
$this->getRequest()->getParam('id') - actually this is the answer
to the question, how to get the submitted data
Data is set to model, and then saved to the DB via call to the
$model->setIsRead(1)->save()
It is strongly encouraged to follow the same approach of working with models. This makes codes much better and easier to support.
Note, that "M" letter of "MVC" architecture in Magento is represented by two layers: Models and Resource Models.
Models:
Contain business logic of an entity. E.g. adding ten items to a
Shopping Cart model triggers a discount rule
Represented by classes with a general name of <Your_Module>_Model_<Model_Name>
If need to work with DB, then extend Mage_Core_Model_Abstract and have a Resource
Model, which is responsible for DB communication
Do not need to have basic save/load methods to be implemented, as the ancestor
Mage_Core_Model_Abstract already has all that routines ready to use
Created via call to Mage::getModel('<your_module>/<model_name>')
Resource Models:
Serve as DB abstraction layer, thus save/load data from DB, perform
other DB queries
Extend Mage_Core_Model_Resource_Db_Abstract in order to communicate with DB
Represented by classes with a general name of
<Your_Module>_Model_Resource_<Model_Name>
Automatically created by a corresponding model, when it needs to communicate with DB
So, in a controller you care about creating Models only. Resource Models are created by a Model automatically.
And, according to everything said above, your controller should look like:
public function testAction()
{
$model = Mage::getModel('your_module/your_model');
$model->setName('andy');
$model->save();
}
You can download a fully working example of the thing you need here.
There can be several variations to the code provided, depending on your specific case. But it represents a general approach to implementing the thing you want.