I have a form that needs to generate slug, I use laravel-admin by z-song.
link: https://github.com/z-song/laravel-admin/
In documentation, a form can simply like this:
protected function form()
{
$form = new Form(new Post);
$form->text('title');
$form->hidden('slug');
return $form;
}
buts it's both manual input. that's not what I need since slug needs to be auto-generated.
I am trying do like this:
protected function form()
{
$form = new Form(new Post);
$form->text('title', 'Title');
$form->hidden('slug')->value(str_slug($form->title));
return $form;
}
buts its result NULL for the slug one.
so how to make it happen?
Laravel admin has some callbacks on $form, that can be useful for generating slug case :
use Illuminate\Support\Str;
$form->text('title');
$form->hidden('slug');
$form->saving(function (Form $form) {
$form->slug = Str::slug($form->title);
});
Note : You can read more about Laravel Helpers, ex. Str::slug.
Related
I'm trying to create a new record to my database using Vue.js in laravel, my API, data is okay. But I get that strange error when I click create on my site.
Argument 1 passed to Illuminate\Database\Grammar::parameterize() must be of the type array, string given, called in C:\Users\PC\Desktop\Productivity\gitdemo\students\vendor\laravel\framework\src\Illuminate\Database\Query\Grammars\Grammar.php on line 884
I also have delete function that works perfectly, but this doesn't work... Form inputs have v-model, that seems alright, but it still doesn't work.
My create method on vue.js
addStudent() {
axios.post(`api/students/create`, {data:this.students});
}
Getting records in vue.js
data() {
return{
students: [],
}
},
created() {
axios.get(`api/students`).then(response =>{
this.students = response.data.data;
})
},
Controller
public function store(Request $request)
{
Student::create($request->all());
return view('welcome');
}
Route (in api.php)
Route::post('students/create', 'StudentController#store');
Student Model
use SoftDeletes;
protected $dates = ['birth_date'];
protected $guarded = [];
Students array in data has all of the v-model namings
You should not directly pass $request->all() to create method. Based on what you send from front end to back end, do this:
$r = $request->all();
$students = $r['data'];
Student:create($students);
just started using Laravel but want to make sure I am using it correctly.
Most of my work is CMS based so read / write / update etc to a database.
An example of what I have done so far is an insertion into the DB:
On the view I have a form with a URL of 'addNewUser'.
In my routes I then do:
Route::post('addnewuser', array('uses' => 'UserController#addNewUser'));
My user controller 'addNewUser' method is (simplified):
public function addNewUser() {
$data = Input::all();
$rules = array(
'username' => 'required|alpha_dash|max:16|unique:users,username',
);
$validator = Validator::make($data, $rules, $messages);
if ($validator->fails())
{
Input::flash();
$errors = $validator->messages();
return Redirect::to('/register')->withErrors($validator)->withInput();
}
$user = new User;
$user->save();
return Redirect::to('/login')->with('successLogin', '1');
}
Is this correct? I have read somewhere that all DB interaction should be in the model?
Likewise when reading from the DB to display a foreach for example, I do the following directly in the view:
$builds = DB::table('blogs')->orderBy('id', 'desc')->get();
if ($builds) {
foreach ($builds as $build)
{
$safeURLSlug = stringHelpers::safeURLSlug($build->blogtitle);
echo "
// stuff
";
}
} else {
// no stuff
}
Should I be doing these sort of queries and showing of data directly in the view? or in a model / controller function etc?
Want to check im doing things 100% correct / the standard way of doing things before I get too involved.
I can see a few things that I personally would have done differently.
For example I usually put $rules as a class variable so it can be used in different functions related to your Users.
Have you tested your code yet? Any errors?
In your addNewUser function does it save any data? I know you have "simplified" above the code snippet but there should be $user->username = $data['username']; etc. in between creating your $user variable and running $user->save();, so if you excluded this on purpose then I don't see anything else with your model.
In your view code, $builds = DB::table('blogs')->orderBy('id', 'desc')->get(); should be done in your controller and passed to your view like so return View::make('example', array('builds' => $builds))
I'd also change
$builds = DB::table('blogs')->orderBy('id', 'desc')->get();
to
$builds = Blog::orderby('id','desc')->get(); if you have a Blog model, otherwise your code is fine.
You could move:
$rules = array(
'username' => 'required|alpha_dash|max:16|unique:users,username',
);
to User model as static variable, and instead of:
$validator = Validator::make($data, $rules, $messages);
you could use:
$validator = Validator::make($data, User::$rules, $messages);
But definitely you shouldn't get data from database in your View, this code should be in controller, for example:
$builds = DB::table('blogs')->orderBy('id', 'desc')->get();
return View::make('someview')->with('builds', $builds);
of course if you have Blog model, you should use here:
$builds = Blog::orderBy('id', 'desc')->get();
return View::make('someview')->with('builds', $builds);
It's also unclear what the following code does:
$safeURLSlug = stringHelpers::safeURLSlug($build->blogtitle);
but probably you could move it to your Blog model and use accessor to make the change:
public function getSafeSlugAttribute($value) {
return stringHelpers::safeURLSlug($this->blogtitle);
}
and now your view could look like this:
#foreach ($builds as $build)
{{{ $build->title }}} {{{ $build->safeSlug }}}
#endforeach
I suggest you take a look on Laravel Generators.
https://github.com/JeffreyWay/Laravel-4-Generators
Install and then run:
php artisan generate:scaffold customer
Laravel line command generator create a basic CRUD for you with controller, model, views and database migrations. That's good to safe time and keep your project with some default organization.
I have form like this :
name (required).
slug (required).
slug is required in back end but user is allowed to leave it blank in form field ( if user leave slug blank, it will use name as the input instead ).
I have tried with Event form listener but it said You cannot change value of submitted form. I tried with Data transformers like this :
public function reverseTransform($slug)
{
if ($slug) {
return $slug;
} else {
return $this->builder->get('name')->getData();
}
}
return $this->builder->get('name')->getData(); always return null. So I tried like this:
public function reverseTransform($slug)
{
if ($slug) {
return $slug;
} else {
return $_POST['category']['name'];
}
}
it works but I think it against the framework. How I can done this with right way?
You can also do it in the controller
if ($form->isValid()) {
$em = $this->getDoctrine()->getManager();
// get the data sent from your form
$data = $form->getData();
$slug = $data->getSlug();
// if no slug manually hydrate the $formObject
if(!$slug)
{
$formObject->setSlug($data->getName());
}
$em->persist($formObject);
$em->flush();
return ....
}
}
If you use a function to keep the code at one place then you should also not work with Request data.
In the form action you call that function including the name variable.
public function reverseTransform($name, $slug)
{
if (!empty($slug)) {
return $slug;
} else {
return $name;
}
}
Another possible way is to set via request class like this:
Array form <input name="tag['slug']"...>:
public function createAction(Request $request)
{
$postData = $request->request->get('tag');
$slug = ($postData['slug']) ? $postData['slug'] : $postData['name'];
$request->request->set('tag', array_merge($postData,['slug' => $slug]));
.......
Common form <input name="slug"...>:
$request->request->set('slug', 'your value');
I think this is the best way because if you are using dml-filter-bundle you don't need to filter your input in your controller like this again:
$this->get('dms.filter')->filterEntity($entity);
Hello is it possible to map fields inside Symfony2 form object, for example my template has field named: "title", but symfony form type want this field as "progress[title]" is it possible to map "title" as "progress[title]" inside form builder?
example:
$builder->add('title')
name:
public function getName()
{
return 'progress';
}
controller handle request needs now "progress[title]", i want send just "title"
$progress = new Progress();
$form = $this->createForm(new ProgressType(), $progress);
$form->handleRequest($request);//here comes "title"
This does not work:
Maybe you can just remove the name?
public function getName()
{
return 'progress';
}
This does:
Else if you want to keep your name and can register the type as service, you can maybe do it like this: Use createNamed with "null" as first parameter.
$form = $formFactory->createNamed(null, 'progress', $progress);
Edit:
For PUT try this:
$form = $formFactory->createNamed(null, 'progress', $progress, array('method'=>'PUT'));
Can we edit the possible options for a choice field after the field has been created?
Let's say, the possible options for the choice field(a drop down box for categories) comes from my database. My controller would look like this:
public function addAction(Request $request){
//get the form
$categories = $this->service->getDataFromDatabase();
$form = $this->formFactory->create(new CategoryType(), $categories);
$form->handleRequest($request);
if ($form->isValid()) {
// perform some action, such as saving the task to the database, redirect
}
return $this->templating->renderResponse('TestAdminBundle:Categories:add.html.twig',
array('form' => $form->createView())
);
}
This works. $categories is populated as a dropdown box so the user can select a category. What I don't like about this code is that it has to hit the "getDataFromDatabase" service again when the user hits submit and the form validates the input. This feels unnecessary to me; ideally it should only need to hit the service when validation fails and the form has to be regenerated for the user. I'm hoping to make the controller look something like this:
public function addAction(Request $request){
//get the form
$form = $this->formFactory->create(new CategoryType());
$form->handleRequest($request);
if ($form->isValid()) {
// perform some action, such as saving the task to the database, redirect
}
$categories = $this->service->getDataFromDatabase();
$form->setData($categories); //this tells the choice field to use $categories to populate the options
return $this->templating->renderResponse('TestAdminBundle:Categories:add.html.twig',
array('form' => $form->createView())
);
}
You need to use EventSubscriber, check the docs, here: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html#cookbook-form-events-underlying-data