Use URL slug in cakephp 3.x - cakephp-3.0

I can create without problem a record slug with the title in cakephp 3.x. Now I want to use that field slug on the URL.
How can I do that?
I try with the typical function view changing $id by $slug...
public function view($slug = null)
{
$noticia = $this->Noticias->get($slug, [
'contain' => ['Categorias', 'Usuarios', 'Etiquetas', 'Fotos']
]);
$this->set('noticia', $noticia);
$this->set('_serialize', ['noticia']);
}
but I have the following error: "Record not found in table "noticias".
Thank you

The get() method can only be used to find record by primary key. Instead, you need to use find():
$noticia = $this->Noticias
->findBySlug($slug)
->contain(['Categorias', 'Usuarios', 'Etiquetas', 'Fotos'])
->firstOrFail();

Related

Retrieve specific data using JSON decode Laravel

I'm new to Laravel. I need to retrieve specific data from the database using the JSON decode. I am currently using $casts to my model to handle the JSON encode and decode.
This is my insert query with json encode:
$request->validate([
'subject' => 'required|max:255',
'concern' => 'required'
]);
$issue = new Issue;
$issue->subject = $request->subject;
$issue->url = $request->url;
$issue->details = $request->concern;
$issue->created_by = $request->userid;
$issue->user_data = $request->user_data; //field that use json encode
$issue->status = 2; // 1 means draft
$issue->email = $request->email;
$issue->data = '';
$issue->save();
The user_data contains {"id":37,"first_name":"Brian","middle_name":"","last_name":"Belen","email":"arcega52#gmail.com","username":"BLB-Student1","avatar":"avatars\/20170623133042-49.png"}
This is my output:
{{$issue->user_data}}
What I need to retrieve is only the first_name, middle_name, and last_name. How am I supposed to achieve that? Thank you in ADVANCE!!!!!
As per the above code shown by you it will only insert data into the database.For retrieving data you can make use of Query Builder as i have written below and also you can check the docs
$users = DB::table('name of table')->select('first_name', 'middle_name', 'last_name')->get();
I will recommend using Resources. It really very helpful laravel feature. Check it out. It is a reusable class. You call anywhere and anytime.
php artisan make:resource UserResource
Go to your the newly created class App/Http/Resources/UserResource.php and drfine the column you want to have in your response.
public function toArray($request) {
return [
"first_name" => $this->first_name,
"middle_name" => $this->middle_name,
"last_name" => $this->last_name
]
}
Now is your controller you can use the UserResource like folow:
public function index()
{
return UserResource::collection(User::all());
}
Or after inserting data you can return the newly added data(f_name, l_name...)
$user = new User;
$user->first_name= $request->first_name;
$user->middle_name= $request->middle_name;
$user->last_name= $request->last_name;
$user->save();
$user_data= new UserResource($user);
return $user_data;

Yii2 - Checkboxlist Value Store In Database

in my db structure
service_request type enum('towel','tissue','napkin')
then have a model
* #property string $service_request
then in my view
<?= $form->field($model, 'service_request')->checkBoxList([ 'towel' => 'Towel', 'tissue' => 'Tissue', 'napkin' => 'Napkin']) ?>
then when i choose towel, tissue and napkin then submit the form, it's have an error said
Service Request must be String
please help me
Thank You
Like Joji Thomas said, checkBoxList prodices an array.
You need to change your database structure so that it supports 1-to-many relations (each $model can have multiple service_requests) if you want to save this. Unfortunately Yii is not very good at this sort of thing out of the box so you have to do a bunch of things yourself.
First you need to create a ServiceRequest ActiveRecord.
Then your $model needs to have a relation like:
public function getServiceRequests() {
return $this->hasMany(ServiceRequest::className(), ['model_id' => 'id'];
}
Then in your controller (model create action) you will need to do something like this:
foreach (Yii::$app->request->post('ServiceRequest',[]) as $data) {
$item = new ServiceRequest($data);
$model->link('serviceRequests', $item);
}
If you wanna update the checkboxes too then you need to do something similar in your model update action as well.
Please change checkBoxList to radioList, because when selecting multiple values service_request becomes an array. Enum type can handle only string values.
First change your filed datatype from enum to varchar. enum only takes a single string value.
Secondly you need to implode service_request array to string for save to db.
Use bellow code before the model save function :
$model->service_request = implode("," , $model->service_request);
$model->save();

Cakephp 3: Modifying Results from the database

In my database there is a content table and when fetching data from this table I would like to append field url to the results, which is based on slug field which is contained in the table. Anyway, I have seen a way to do this in the previous versions of cakephp using behavior for the model of this table and then modifying results in afterFind callback in the behavior class. But in version 3 there is no afterFind callback, and they recommend using mapReduce() method instead in the manual, but this method is poorly explained in the manual and I cant figure out how to achieve this using mapReduce().
After little bit of research I realized that the best way to append the url field field to find results is using formatResults method, So this is what I did in my finders:
$query->formatResults(function (\Cake\Datasource\ResultSetInterface $results) {
return $results->map(function ($row) {
$row['url'] = array(
'controller' => 'content',
'action' => 'view',
$row['slug'],
$row['content_type']['alias']
);
return $row;
});
});

How to use article name on the url on Yii2?

I need to use article name on the url on Yii2 which is like http://example.com/article?id=1, just replace id=1 to article_name, like http://example.com/article/article_name or is it.
This is my controller code-
$model = Articles::find()->orderBy(['id' => SORT_DESC])->one();
View-
<?= Html::a('<b>Read more ...</b>', ['article-details','id' => $model->id], ['target'=>'_blank']) ?>
Thanks advance
You may use yii2 sluggable behavior Refer this.
There are few steps.
You must add the following urlManager rule :
'article/<slug>' => 'article/view',
You should build url in your view files like this :
\yii\helpers\Url::to(['article/view', 'slug'=>$model->title])
or
\yii\helpers\Url::to(['article/'.$model->title]);
And in your action
public function actionArticle($slug){
$model = Articles::find()->where(["title"=>$slug])->orderBy(['id' => SORT_DESC])->one();
//and other code
}
Also your article titles must be valid for url.You can do it easly by trimming whitespaces and so on But also you can add url some identification propery. or add column stored unique slugs for every article
You have two way
one change the related action in the controller changing id with name in the related function declaration
or declare a new action with the name as parameter
public function findModelName($article_name)
{
$model = Article::findOne(['name'=> $article_name]);
........ your related code
}
you can find the model by name this way
Article::findOne(['name'=> $article_name]);

cakePHP update table fields

I have a cakePHP problem - I want to make a update query like this
UPDATE table SET field = field + some_var
and I don't know how to do it...
Can anyone help me?
The only "right" way would be using cake's "atomic query" wrapper methods. In your case that would be "updateAll".
The question is a complete duplicate of a dozen other questions - like Incrementing Cakephp database field by a value
$var = 1;
$this->Article->updateAll(
array('Article.viewed' => 'Article.viewed + ' . $var),
array('Article.id' => $id)
);
This is also in the docs: http://book.cakephp.org/2.0/en/models/saving-your-data.html#model-updateall-array-fields-array-conditions
There are two ways to do an update:
If you are only updating one field you can do:
$this->Model->id = foo;
$this->Model->saveField('field_name', 'field_value');
or, you can do an update using $this->Model->save():
$data = array(
'Model'=>array(
'id'=>foo,
'field_name'=>'field_value',
'another_field_name'=>'another_field_value'
)
);
$this->Model->save($data);
You want to avoid using $this->Model->query() and use CakePHP's built in methods because the build in methods are datasource agnostic (they work the same on MySQL, Oracle, MSSQL etc.)
You can use the callback method beforeSave to implement what you need.
Callback Method: BeforeSave
public function beforeSave($options = array()) {
if (!empty($this->data['table']['field'])){
$this->data['table']['field'] += $this->data['table']['some_var'];
}
return true;
}
I think the best method is using the Model::updateAll(array $fields, array $conditions).
The Model::saveField(string $fieldName, string $fieldValue, $validate = false) this method when you try to update using same primary key it shows cannot replace duplicate key error. And think when one updates they must be using the primary key as a matching value to update value.
Use
$this->Baker->updateAll(
array('Baker.approved' => 'Baker.approved + ' . $some_var),
array('Baker.id' => $someId)
);
For more information see: http://book.cakephp.org/2.0/en/models/saving-your-data.html