Quantcast
Channel: Live News for Yii Framework
Viewing all 3361 articles
Browse latest View live

[extension] pcrt/yii2-latex

$
0
0

Yii2-Latex

  1. Installation
  2. Usage
  3. License

Latex2PDF formatter for Yii2 .

This extension "format" Latex responses to PDF files (by default Yii2 includes HTML, JSON and XML formatters). Great for reports in PDF format using Latex views/layouts.

Installation

The preferred way to install this extension is through composer.

Either run

$ php composer.phar require pcrt/yii2-latex "*"

or add

"pcrt/yii2-pdf": "*"

to the require section of your composer.json file.

Usage

Once the extension is installed, modify your application configuration to include:

return [
	'components' => [
		...
		'response' => [
			'formatters' => [
				'pdf' => [
					'class' => 'pcrt\latex\Latex2PdfResponseFormatter',
					'latexbin' => '/usr/local/bin/pdflatex',
					'buildpath' => '/folder/you/prefer' // for default use current folder
					'keepfile' => false // if true not clean debug file ( debug purpose only )
 				],
			]
		],
		...
	],
];

For default the buildpath variable is set on your @webroot folder .

In the controller:


class MyController extends Controller {
	public function actionPdf(){
		Yii::$app->response->format = 'latex';
		$this->layout = '//print'; // A siple template without any html code
		return $this->render('myview', []);
	}
}

License

Yii2-Latex is released under the BSD-3 License. See the bundled LICENSE.md for details.

Useful URLs

  1. Installation
  2. Usage
  3. License

Enjoy!


[extension] pcrt/yii2-gii

$
0
0

Yii2-gii

  1. Installation
  2. Usage
  3. License

Additional Gii code generator .

This extension add code generator to Yii2 framework Gii extension.

Installation

The preferred way to install this extension is through composer.

Either run

$ php composer.phar require pcrt/yii2-gii "*"

or add

"pcrt/yii2-gii": "*"

to the require section of your composer.json file.

Usage

Once the extension is installed, modify your application configuration to include:



  $config['modules']['gii'] = [
      'class' => 'yii\gii\Module',
      ....
      'generators' => [ // HERE
          'pcrtmodel' => [
              'class' => 'pcrt\generators\model\Generator',
              'templates' => [
                  'pcrt' => '@vendor/pcrt/yii2-gii/generators/model/pcrt',
              ]
          ],
          'pcrtcrud' => [
              'class' => 'pcrt\generators\crud\Generator',
              'templates' => [
                  'pcrt' => '@vendor/pcrt/yii2-gii/generators/crud/pcrt',
              ]
          ]
      ],
      ....
      // uncomment the following to add your IP if you are not connecting from localhost.
      // 'allowedIPs' => ['127.0.0.1', '::1'],
  ];

License

Yii2-gii is released under the BSD-3 License. See the bundled LICENSE.md for details.

Enjoy!

[extension] pcrt/yii2-ajax-pager

$
0
0

Yii2-Ajax-Pager

  1. Installation
  2. Usage
  3. License

Yii2 Component extend yii\widgets\ContentDecorator url used to add ajax-pagination functionality to GridView and ListView base component .

This extension create a Wrapper around content and permit to chose between "Paginator Pattern" or "InfiniteScroll Pattern" to manage pagination functionality without reload page .

Installation

The preferred way to install this extension is through composer.

Either run

$ php composer.phar require pcrt/yii2-ajax-pager "@dev"

or add

"pcrt/yii2-ajax-pager": "@dev"

to the require section of your composer.json file.

Usage

Once the extension is installed, you can add component in your View: The component can work as Pagination :

use pcrt/Paginator;
....

<?php Paginator::begin([
    'type' => 'Pagination',
    'id' => 'pcrt-pagination', // Id of pagination container
    'id_wrapper' => 'pcrt-pagination-wrapper', // Id of wrapper container
    'view' => $this,
]) ?>

$this->renderPartial('ajax/list', [ 'dt' => $dataProvider ]);
// or do your magic here !

<?php Paginator::end() ?>

or in InfiniteScroll mode:

use pcrt/Paginator;
....

<?php Paginator::begin([
    'type' => 'InfiniteScroll',
    'append' => '.pcrt-card', // Selector for pagination element extractor
    'id_wrapper' => 'pcrt-pagination-wrapper', // Id of wrapper container
    'view' => $this,
]) ?>

$this->renderPartial('ajax/_card', [ 'dt' => $dataProvider ]);
// or do your magic here !

<?php Paginator::end() ?>

You can also pass an alternative "wapper view" file :

use pcrt/Paginator;
....

<?php Paginator::begin([
    'type' => 'InfiniteScroll',
    'viewFile' => '@app/views/wrapper.php', // Alternative view Wrapper
    'append' => '.pcrt-card', // Selector for pagination element extractor
    'id_wrapper' => 'pcrt-pagination-wrapper', // Id of wrapper container
    'view' => $this,
]) ?>

// Remenber to return $content variable inside of wrapper;

In the controller for InfiniteScroll return a renderAjax file:

class MyController extends Controller {

  public function actionGetGridView(){

    public function actionGetGridView($pageNumber=0,$pageSize=50){
      if($pageSize == ""){
        $pageSize = 50;
      }
      $request = \Yii::$app->request;

      $searchModel = new MyControllerSearch();
      $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
      $dataProvider->pagination = [
              'pageSize'=>$pageSize,
              'page'=>$pageNumber-1,
      ];
      $result = $dataProvider->getTotalCount();
      $data = $this->renderAjax('_list', [
          'searchModel' => $searchModel,
          'dataProvider' => $dataProvider,
      ]);
      return $data;

  	}
	}

}

for Pagination return a jSON Object with data (html render) and total (total number of element):

class MyController extends Controller {

  public function actionGetGridView($pageNumber=0,$pageSize=50){
    \Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
    if($pageSize == ""){
      $pageSize = 50;
    }
    $request = \Yii::$app->request;

    $searchModel = new MyControllerSearch();
    $dataProvider = $searchModel->search();
    $dataProvider->pagination = [
            'pageSize'=>$pageSize,
            'page'=>$pageNumber-1,
    ];
    $result = $dataProvider->getTotalCount();
    $data = $this->renderAjax('_list', [
        'searchModel' => $searchModel,
        'dataProvider' => $dataProvider,
    ]);
    return ['html'=>$data,'total'=>$result];
	}
}

License

Yii2-Ajax-Pager is released under the BSD-3 License. See the bundled LICENSE.md for details.

Useful URLs

  1. Installation
  2. Usage
  3. License

Enjoy!

[extension] pcrt/yii2-datepicker

$
0
0

Yii2-Datepicker

  1. Installation
  2. Usage
  3. License

Daterangepicker gives you a customizable daterangepicker with support for multidate, time, localization and many other highly used options.

Installation

The preferred way to install this extension is through composer.

Either run

$ php composer.phar require pcrt/yii2-datepicker "*"

or add

"pcrt/yii2-datepicker": "*"

to the require section of your composer.json file.

Usage

Once the extension is installed, modify your application configuration to include:

use pcrt\widgets\datepicker\Datepicker:


// with \yii\bootstrap\ActiveForm;
echo $form
    ->field($model, 'attribute')
    ->widget(
        Datepicker::class,
        [
          'clientOptions' => [
            'singleDatePicker' => true,
            'showDropdowns' => true,
          ]
        ]
    );

// as widget
echo Datepicker::widget([
    'clientOptions' => [
      'showDropdowns' => true,
    ]
]);

License

Yii2-Datepicker is released under the BSD-3 License. See the bundled LICENSE.md for details.

Enjoy!

[news] Yii 2.0.16.1 is released

[extension] immusen/yii2-swoole-mqtt

$
0
0

MQTT For Yii2 Base On Swoole 4

  1. Installation
  2. Test or Usage
  3. Example:
  4. Coding:

MQTT server for Yii2 base on swoole 4, Resolve topic as a route reflect into controller/action/param, And support redis pub/sub to trigger async task from your web application

Installation

Install Yii2: Yii2.

Install swoole: swoole, recommend version 4+.

Other dependency: php-redis extension.

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist immusen/yii2-swoole-mqtt "~1.0"

or add

"immusen/yii2-swoole-mqtt": "~1.0"

to the require section of your composer.json file.

Test or Usage

# after installation, cd project root path, e.g. cd yii2-advanced-project/
mv vendor/immusen/yii2-swoole-mqtt/example/mqtt ./
mv vendor/immusen/yii2-swoole-mqtt/example/mqtt-server ./
chmod a+x ./mqtt-server
# run:
./mqtt-server
# config :
cat ./mqtt/config/params.php
<?php
return [
    'listen' => 8721,
    'daemonize' => 0,
    'auth' => 1, // config auth class in ./main.php
];
# or coding in ./mqtt/controllers/

Test client: MQTTLens, MQTT.fx

Example:

Case A: Subscribe/Publish

1, mqtt client subscribe topic: room/count/100011

2.1, mqtt client publish: every time publish topic: room/join/100011, the subscribe side will get count+1, or publish topic: room/leave/100011 get count -1.

2.2, redis client pulish: every time $redis->publish('async', 'room/join/100011'), the subscribe side will get count+1, or $redis->publish('async', 'room/leave/100011') get count -1.

Case B: Publish(Notification Or Report)

mqtt client publish topic: report/coord/100111 and payload: e.g. 110.12345678,30.12345678,0,85

Coding:

MQTT subscribe topic: "channel/count/100001" will handle at: `

class ChannelController{
    public function actionCount($channel_id){
        echo "client {$this->fd} subscribed the count change of channel {$channel_id}";
    }
}
> //client 1 subscribed the count change of channel 100001


MQTT Publish Topic:  "channel/join/100001"  with payload: "Foo"  will handle at:
class ChannelController{
    public function actionJoin($channel_id, $who){
        echo "{$who} join in channel {$channel_id}";
        #then broadcast update to all client who subscribed channel 100001
        #$this->publish($fds, $sub_topic, $count);
    }
}
> // Foo join in channel 100001

MQTT
----

About MQTT: [MQTT Version 3.1.1 Plus Errata 01](http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/mqtt-v3.1.1.html)

> Non-complete implementation of MQTT 3.1.1 in this project, Upgrading...

[extension] immusen/yii2-swoole-websocket

$
0
0

Websocket rpc server For Yii2 Base On Swoole 4

  1. Installation
  2. Test or Usage
  3. Example:
  4. Coding:

Websocket server for Yii2 base on swoole 4, Support JSONRPC, Resolve 'method' as a route reflect into controller/action, And support http or redis pub/sub to trigger async task from your web application.

Installation

Install Yii2: Yii2.

Install swoole: swoole, recommend version 4+.

Other dependency: php-redis extension.

The preferred way to install this extension is through composer.

Either run

php composer.phar require --prefer-dist immusen/yii2-swoole-websocket "~1.0"

or add

"immusen/yii2-swoole-websocket": "~1.0"

to the require section of your composer.json file.

or unzip code into vendor directory and then add

'immusen/yii2-swoole-websocket' => 
     array (
       'name' => 'immusen/yii2-swoole-websocket',
       'version' => 'dev',
       'alias' => 
       array (
         '@immusen/websocket' => $vendorDir . '/immusen/yii2-swoole-websocket',
       ),
     ),

to vendor/yiisoft/extensions.php

Test or Usage

after installation, cd project root path, e.g. cd yii2-advanced-project/ mv vendor/immusen/yii2-swoole-websocket/example/websocket ./ mv vendor/immusen/yii2-swoole-websocket/example/websocket-server ./ chmod a+x ./websocket-server run: ./websocket-server config : ` vim ./websocket/config/params.php <?php return [

'listen' => 8721,
'daemonize' => 0,

]; ` or coding in ./websocket/controllers/

Example:

Chat room demo, code: ./websocket/controllers/RoomController.php

client join room: websocket client send:

`

{
    "jsonrpc":"2.0",
    "id":1,
    "method":"room/join",
    "params":{
        "id":"100111",
        "info":{
            "age":"19",
            "gender":"f"
        }
    }
}

> the websocket client which had joined same room (id:100111) will get message like this:

{
    "jsonrpc":"2.0",
    "id":1,
    "result":{
        "type":"join",
        "count":85,
        "info":{
            "age":"19",
            "gender":"f"
        }
    }
}

`

chat message websocket client send: `

{
    "jsonrpc":"2.0",
    "id":1,
    "method":"room/msg",
    "params":{
        "id":"100111",
        "content":{
            "text":"Hello world!"
        }
    }
}
this room member will get:
{
    "jsonrpc":"2.0",
    "id":1,
    "result":{
        "text":"Hello world!"
    }
}

Coding:

1, Create Controller under websocket/controllers, or other path which defined with "controllerNamespace" in websocket/config/main.php ` <?php namespace websocket\controllers;

use immusen\websocket\src\Controller;

class FooController extends Controller {

 public function actionBar($param_1, $param_2 = 0, param_n = null)
 {
      # add current fd into a group/set, make $param_1 or anyother string as the group/set key
      $this->addFds($this->fd, $param_1);
      
      # reply message to current client by websocket
      $this->publish($this->fd, ['p1' => param_1, 'p2' => param_2]);
      
      # get all fds stored in the group/set
      $fds_array = $this->getFds($param_1);
      
      # reply message to a group
      $this->publish($fds_array, ['p1' => param_1, 'p2' => param_2]);
      
      # operate redis via redis pool
      $this->redis->set($param_1, 0)
 }
 
 public function actionBaz()
 {
      //...
 }

} `

2, Send RPC JSON to trigger that action `

{
    "jsonrpc":"2.0",
    "id":1,
    "method":"foo/bar",
    "params":{
        "param_1":"client_01",
        "param_2":100,
        "param_n":{
            "time":1551408888,
            "type":"report"
        }
    }
}

---

All of client to server rpc command also can send by HTTP or Redis publish, This feature will helpful for some async task triggered from web application. Example in chat room case: 

HTTP request: 

http://127.0.0.1:8721/rpc?p={"jsonrpc":"2.0","id":1,"method":"room/msg","params":{"id":"100111","content":{"text":"System warning!"}}} OR redis-cli: 127.0.0.1:6379> publish rpc '{"jsonrpc":"2.0","id":1,"method":"room/msg","params":{"id":"100111","content":{"text":"System warning!"}}}' OR in Yii web application Yii:$app->redis->publish('rpc', '{"jsonrpc":"2.0","id":1,"method":"room/msg","params":{"id":"100111","content":{"text":"System warning!"}}}') `

[news] Yii release cycle clarified

$
0
0

We have added a new page to yiiframework.com website called "release cycle". Its purpose is to clarify about how long a certain framework version will be supported.

Default policy is that after current major version release previous major version has:

  • Two years of bug fixes.
  • Three years of security and PHP compatibility fixes.

For example, in case Yii 3.0 is released today, 2.0 will receive bugfixes till March 2021 and security fixes till March 2024.


[extension] zhuravljov/yii2-queue-monitor

$
0
0

Yii2 Queue Analytics Module

  1. Installation
  2. Usage

The module collects statistics about working of queues of an application, and provides web interface for research. Also the module allows to stop and replay any jobs manually.

Latest Stable Version Total Downloads Scrutinizer Code Quality

Installation

The preferred way to install the extension is through composer. Add to the require section of your composer.json file:

"zhuravljov/yii2-queue-monitor": "~0.1"

Usage

To configure the statistics collector, you need to add monitor behavior for each queue component. Update common config file:

return [
    'components' => [
        'queue' => [
            // ...
            'as jobMonitor' => \zhuravljov\yii\queue\monitor\JobMonitor::class,
            'as workerMonitor' => \zhuravljov\yii\queue\monitor\WorkerMonitor::class,
        ],
    ],
];

There are storage options that you can configure by common config file:

return [
    'container' => [
        'singletons' => [
            \zhuravljov\yii\queue\monitor\Env::class => [
                'cache' => 'cache',
                'db' => 'db',
                'pushTableName'   => '{{%queue_push}}',
                'execTableName'   => '{{%queue_exec}}',
                'workerTableName' => '{{%queue_worker}}',
            ],
        ],
    ],
];

If you want use migrations of the extension, configure migration command in console config:

'controllerMap' => [
    'migrate' => [
        'class' => \yii\console\controllers\MigrateController::class,
        'migrationNamespaces' => [
            //...
            'zhuravljov\yii\queue\monitor\migrations',
        ],
    ],
],

And apply migrations.

Finally, modify your web config file to turn on web interface:

return [
    'bootstrap' => [
        'monitor',
    ],
    'modules' => [
        'monitor' => [
            'class' => \zhuravljov\yii\queue\monitor\Module::class,
        ],
    ],
];

It will be available by URL http://yourhost.com/monitor.

[extension] codemonauts/yii2-cloudwatch-logs

$
0
0

Yii2 Cloudwatch Logs Target

  1. Installation and Configuration
  2. Configuration Options
  3. Cloudwatch Logs Insights

A Yii2 log target for AWS Cloudwatch Logs.

Installation and Configuration

Install the package through composer:

composer require codemonauts/yii2-cloudwatch-logs

And then add this to your application configuration:

<?php
return [
    // ...
    'components' => [
        // ...
        'log' => [
            'targets' => [
                [
                    'class' => \codemonauts\cloudwatchlogs\Target::class,
                    'region' => 'eu-west-1',
                    'logGroup' => '/webserver/production/my-craft',
                    'logStream' => 'instance-1', // omit for automatic instance ID
                    'levels' => ['error', 'warning', 'info', 'trace', 'profile'],
                    'logVars' => ['_GET', '_POST', '_FILES', '_COOKIE', '_SESSION', '_SERVER'],
                    'key' => 'your-key', // omit for instance role
                    'secret' => 'your-secret', // omit for instance role
                ],
                // ...
            ],
        ],

Configuration Options

  • (string) $region (required) The name of the AWS region e.g. eu-west-1
  • (string) $logGroup (required) The name of the log group.
  • (string) $logStream (optional) The name of the log stream. If omitted, it will try to determine the ID of the EC2 instance running on.
  • (array) $levels (optional) Log level. Default by Yii2: ['error', 'warning', 'info', 'trace', 'profile']
  • (array) $logVars (optional) Variables to log. Default by Yii2: ['_GET', '_POST', '_FILES', '_COOKIE', '_SESSION', '_SERVER']
  • (string) $key (optional) Your AWS access key.
  • (string) $secret (optional) Your AWS secret.

Cloudwatch Logs Insights

If you want to parse the logs with Insights, then do something like this:

fields @timestamp, @message
| sort @timestamp desc
| limit 20
| parse '[*][*][*][*][*] *' as ip, userId, sessionId, logLevel, category, message

[extension] andmemasin/actionlog

[extension] andmemasin/yii2-emails-validator

[extension] tonisormisson/yii2-address-form

$
0
0

Yii2 Address-form module

  1. powered by rinvex/country
  2. Example

Scrutinizer Code Quality Build Status Code Coverage

A module doing address-form fields with dependent pre-set country-region drop-downs. Countries & regions powered by:

powered by rinvex/country

250 countries & regions worldwide available

Example

add module config

the module part will take care of dep-drop ajax queries


    'modules' => [
        //...
        'addressform' =>[
            'class' => \tonisormisson\addressform\Module::class,
        ],
        //...
    ]
place the widet
use tonisormisson\addressform\AddressForm; 

echo AddressForm::widget([
    'allowedCountries' => ["EE", "LV", "LT"],
    'placeHolders' = [
        // custom placeholders here if needed
        'country' => ,
        'state' => ,
        'city' => ,
        'postCode' => ,
        'addressLine1' => ,
        'addressLine2' => ,
    ],
            
]);
and catch the address in controller
use tonisormisson\addressform\models\Address;
$address = new Address();
$address->load(Yii::$app->request->post());

// load the address to your models
// eg :
$model->address_data = Json::encode($address);

[wiki] Events registration examples

$
0
0

Register an event handler at Object-Level

e.g inside the init method of a Model

// this should be inside your model class. For example User.php
public function init(){
  $this->on(self::EVENT_NEW_USER, [$this, 'sendMail']);
  $this->on(self::EVENT_NEW_USER, [$this, 'notification']);
  // first parameter is the name of the event and second is the handler. 
  // For handlers I use methods sendMail and notification
  // from $this class.
  parent::init(); // DON'T Forget to call the parent method.
}

taked from https://stackoverflow.com/questions/28575636/how-to-use-events-in-yii2

Register an event handler at Class-Level

To register event handles at Class-Level a good place can be inside the bootstrap process.

So, you can put the registration code as

Event::on(ActiveRecord::className(), ActiveRecord::EVENT_AFTER_INSERT, function ($event) {
    Yii::debug(get_class($event->sender) . ' is inserted');
});

in a php file like the bootstrap.php used in Advanced-Template or through configuration, with your custom component for example

see docs

(https://www.yiiframework.com/doc/guide/2.0/en/structure-applications#bootstrap or https://www.yiiframework.com/doc/guide/2.0/en/structure-extensions#bootstrapping-classes)

[news] Bootstrap 4 extension version 2.0.1 released


[news] Debug extension 2.1.0 released

$
0
0

We are very pleased to announce the release of Debug extension version 2.1.0.

Additionally to bugfixes, there some enhancements:

  1. Module has checkAccessCallback property that you can set to a callable that returns a boolean determining if current user should be allowed to access debug.
  2. New "dump" panel was added. It collects and displays debug messages logged with Logger::LEVEL_TRACE.
  3. New version has less dependencies thanks to simialbi. It doesn't depend on bootstrap package anymore.
  4. There are small visual adjustments as well.

See the CHANGELOG for details.

[news] Gii extension 2.1.0 released

$
0
0

We are very pleased to announce the release of Gii extension version 2.1.0.

Additionally to bugfixes, there are some enhancements in this release:

  1. New version has less dependencies thanks to simialbi. It doesn't depend on bootstrap package anymore.
  2. New option added to singularize class names in modele generator.

See the CHANGELOG for details.

[wiki] Nested Set with Yii2

$
0
0

The nested set behaviour is an approach to store hierarchical data in relational databases. For example, if we have many categories for our product or items. One category can be a "parent" for other categories, means that one category consists of more than one category. The model can be drawn using a "tree" model. There are other approaches available but what we will learn in this article is specifically the NestedSetsBehavior made by Alexander Kochetov, which utilizing the Modified Preorder Tree Traversal algorithm.

Requirements :

  • Yii2 framework advanced template
  • Yii2 nested sets package

Install the package using composer

It is always recommended to use Composer to install any kind of package or extension for our Yii2-powered project.

$ composer require creocoder/yii2-nested-sets

Create the table

In this article, we will use Category for our model/table name. So we would like to generate the table using our beloved migration tool.

$ ./yii migrate/create create_category_table

We need to modify the table so it contains our desired fields. We also generate three additional fields named position, created_at, and updated_at.

<?php

use yii\db\Migration;

/**
 * Handles the creation for table `category`.
 */
class m160611_114633_create_category extends Migration
{
    /**
     * @inheritdoc
     */
    public function up()
    {
        $this->createTable('category', [
            'id'         => $this->primaryKey(),
            'name'       => $this->string()->notNull(),
            'tree'       => $this->integer()->notNull(),
            'lft'        => $this->integer()->notNull(),
            'rgt'        => $this->integer()->notNull(),
            'depth'      => $this->integer()->notNull(),
            'position'   => $this->integer()->notNull()->defaultValue(0),
            'created_at' => $this->integer()->notNull(),
            'updated_at' => $this->integer()->notNull(),
        ]);
    }

    /**
     * @inheritdoc
     */
    public function down()
    {
        $this->dropTable('category');
    }
}

Then, generate the table using the migration tool.

$ ./yii migrate

If everything is okay, then you could see that a new table named category already exists.

Generate the default CRUD using Gii

To initiate a model, we need to use Gii tool from Yii2. Call the tool from your localhost:8080/gii/model, and fill in the Table Name field with our existing table: category. Fill other fields with appropriate values, and don't forget to give a check to "Generate ActiveQuery" checklist item. This will generate another file that needs to be modified later.

Continue to generate the CRUD for our model with CRUD Generator Tool. Fill in each field with our existing model. After all files are generated, you can see that we already have models, controllers, and views but our work is far from done because we need to modify each file.

Modify models, controllers, and views

The first file we should modify is the model file: Category.

<?php

namespace common\models;

use Yii;
use creocoder\nestedsets\NestedSetsBehavior;

/**
 * This is the model class for table "category".
 *
 * @property integer $id
 * @property string $name
 * @property integer $tree
 * @property integer $lft
 * @property integer $rgt
 * @property integer $depth
 * @property integer $position
 * @property integer $created_at
 * @property integer $updated_at
 */
class Category extends \yii\db\ActiveRecord
{
    /**
     * @inheritdoc
     */
    public static function tableName()
    {
        return 'category';
    }

    public function behaviors() {
        return [
            \yii\behaviors\TimeStampBehavior::className(),
            'tree' => [
                'class' => NestedSetsBehavior::className(),
                'treeAttribute' => 'tree',
                // 'leftAttribute' => 'lft',
                // 'rightAttribute' => 'rgt',
                // 'depthAttribute' => 'depth',
            ],
        ];
    }

    public function transactions()
    {
        return [
            self::SCENARIO_DEFAULT => self::OP_ALL,
        ];
    }

    public static function find()
    {
        return new CategoryQuery(get_called_class());
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            [['name'], 'required'],
            [['position'], 'default', 'value' => 0],
            [['tree', 'lft', 'rgt', 'depth', 'position', 'created_at', 'updated_at'], 'integer'],
            [['name'], 'string', 'max' => 255],
        ];
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'id'         => Yii::t('app', 'ID'),
            'name'       => Yii::t('app', 'Name'),
            'tree'       => Yii::t('app', 'Tree'),
            'lft'        => Yii::t('app', 'Lft'),
            'rgt'        => Yii::t('app', 'Rgt'),
            'depth'      => Yii::t('app', 'Depth'),
            'position'   => Yii::t('app', 'Position'),
            'created_at' => Yii::t('app', 'Created At'),
            'updated_at' => Yii::t('app', 'Updated At'),
        ];
    }

    /**
     * Get parent's ID
     * @return \yii\db\ActiveQuery 
     */
    public function getParentId()
    {
        $parent = $this->parent;
        return $parent ? $parent->id : null;
    }

    /**
     * Get parent's node
     * @return \yii\db\ActiveQuery 
     */
    public function getParent()
    {
        return $this->parents(1)->one();
    }

    /**
     * Get a full tree as a list, except the node and its children
     * @param  integer $node_id node's ID
     * @return array array of node
     */
    public static function getTree($node_id = 0)
    {
        // don't include children and the node
        $children = [];

        if ( ! empty($node_id))
            $children = array_merge(
                self::findOne($node_id)->children()->column(),
                [$node_id]
                );

        $rows = self::find()->
            select('id, name, depth')->
            where(['NOT IN', 'id', $children])->
            orderBy('tree, lft, position')->
            all();

        $return = [];
        foreach ($rows as $row)
            $return[$row->id] = str_repeat('-', $row->depth) . ' ' . $row->name;

        return $return;
    }
}

As you can see, we import the extension using the keyword use:

use creocoder\nestedsets\NestedSetsBehavior;

and I also add the TimeStampBehavior for our additional fields, created_at and updated_at

\yii\behaviors\TimeStampBehavior::className(),

Next : Our modification to CategoryController file is at update, create, and delete function.

<?php

namespace backend\controllers;

use Yii;
use common\models\Category;
use common\models\CategorySearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;

/**
 * CategoryController implements the CRUD actions for Category model.
 */
class CategoryController extends Controller
{
    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        return [
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['POST'],
                ],
            ],
        ];
    }

    /**
     * Lists all Category models.
     * @return mixed
     */
    public function actionIndex()
    {
        $searchModel = new CategorySearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

        return $this->render('index', [
            'searchModel' => $searchModel,
            'dataProvider' => $dataProvider,
        ]);
    }

    /**
     * Displays a single Category model.
     * @param integer $id
     * @return mixed
     */
    public function actionView($id)
    {
        return $this->render('view', [
            'model' => $this->findModel($id),
        ]);
    }

    /**
     * Creates a new Category model.
     * If creation is successful, the browser will be redirected to the 'view' page.
     * @return mixed
     */
    public function actionCreate()
    {
        $model = new Category();

        if ( ! empty(Yii::$app->request->post('Category'))) 
        {
            $post            = Yii::$app->request->post('Category');
            $model->name     = $post['name'];
            $model->position = $post['position'];
            $parent_id       = $post['parentId'];

            if (empty($parent_id))
                $model->makeRoot();
            else
            {
                $parent = Category::findOne($parent_id);
                $model->appendTo($parent);
            }

            return $this->redirect(['view', 'id' => $model->id]);
        }

        return $this->render('create', [
                'model' => $model,
            ]);
    }

    /**
     * Updates an existing Category model.
     * If update is successful, the browser will be redirected to the 'view' page.
     * @param integer $id
     * @return mixed
     */
    public function actionUpdate($id)
    {
        $model = $this->findModel($id);

        if ( ! empty(Yii::$app->request->post('Category'))) 
        {
            $post            = Yii::$app->request->post('Category');

            $model->name     = $post['name'];
            $model->position = $post['position'];
            $parent_id       = $post['parentId'];

            if ($model->save())            
            {
                if (empty($parent_id))
                {
                    if ( ! $model->isRoot())
                        $model->makeRoot();
                }
                else // move node to other root 
                {
                    if ($model->id != $parent_id)
                    {
                        $parent = Category::findOne($parent_id);
                        $model->appendTo($parent);
                    }
                }

                return $this->redirect(['view', 'id' => $model->id]);
            }
        }

        return $this->render('update', [
            'model' => $model,
        ]);
    }

    /**
     * Deletes an existing Category model.
     * If deletion is successful, the browser will be redirected to the 'index' page.
     * @param integer $id
     * @return mixed
     */
    public function actionDelete($id)
    {
        $model = $this->findModel($id);

        if ($model->isRoot())
            $model->deleteWithChildren();
        else 
            $model->delete();

        return $this->redirect(['index']);
    }

    /**
     * Finds the Category model based on its primary key value.
     * If the model is not found, a 404 HTTP exception will be thrown.
     * @param integer $id
     * @return Category the loaded model
     * @throws NotFoundHttpException if the model cannot be found
     */
    protected function findModel($id)
    {
        if (($model = Category::findOne($id)) !== null) {
            return $model;
        } else {
            throw new NotFoundHttpException('The requested page does not exist.');
        }
    }
}

As for our views files, we need to remove unnecessary fields from our form, such as the lft, rgt, etc, and add the sophisticated parent field to be a dropdown list. This requires a lot of effort, as you can see on the getTree function on our model.

<?php

use yii\helpers\Html;
use yii\widgets\ActiveForm;

use common\models\Category;

/* @var $this yii\web\View */
/* @var $model common\models\Category */
/* @var $form yii\widgets\ActiveForm */
?>

<div class="category-form">

    <?php $form = ActiveForm::begin(); ?>

    <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>

    <div class='form-group field-attribute-parentId'>
    <?= Html::label('Parent', 'parent', ['class' => 'control-label']);?>
    <?= Html::dropdownList(
        'Category[parentId]',
        $model->parentId,
        Category::getTree($model->id),
        ['prompt' => 'No Parent (saved as root)', 'class' => 'form-control']
    );?>

    </div>

    <?= $form->field($model, 'position')->textInput(['type' => 'number']) ?>

    <div class="form-group">
        <?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
    </div>

    <?php ActiveForm::end(); ?>

</div>

[extension] thtmorais/yii2-pace

$
0
0

PACE (Progress Automatically Certain to Entertain) for Yii PHP Framework

  1. Installation
  2. Usage
  3. Configuration

PACE (Progress Automatically Certain to Entertain) - Automatic page load progress bar for Yii PHP Framework

Installation

The preferred way to install this extension is through composer.

Either run

composer require thtmorais/yii2-pace "*"

or add

"thtmorais/yii2-pace": "*"

to the require section of your composer.json file.

Usage

Once the extension is installed, simply use it in your code by :

<?php

use thtmorais\pace\Pace;

echo Pace::widget();

?>

or

<?= \thtmorais\pace\Pace::widget() ?>

We recommend using in the layouts/main.php file. Or if you prefer in each view file with their respective settings.

Configuration

By default the PACE comes configured with blue color and animation minimal.

You can add general rule for all views in the config/params.php file as follows:

<?php
    return [
        'paceOptions' => [
            'color' =>  'blue',
            'theme' => 'minimal',
            'options' => []
        ]
    ];
?>

or individually in each view:

<?php
   
use thtmorais\pace\Pace;

echo Pace::widget([
    'color'=>'red',
    'theme'=>'corner-indicator',
    'options'=>[]
]);

?>

You can preview themes and colors here.

[extension] luyadev/luya-headless

$
0
0

LUYA Logo

LUYA Headless Client

  1. Installation
  2. Intro
  3. Documentation
  4. Development and Contribution

A client library to access content from the LUYA APIs (or any other REST API).

LUYA Build Status Latest Stable Version Maintainability Test Coverage Total Downloads Slack Support

Compared to the other LUYA packages, this package adheres to Semantic Versioning!

Installation

Add the LUYA headless client library to your composer.json:

composer require luyadev/luya-headless

Intro

Quick intro about how to use the headless library with existing built in active endpoints:

use luya\headless\Client;
use luya\headless\modules\admin\ApiAdminUser;

// build client object with token and server infos
$client = new Client('API_TOKEN', 'http://localhost/luya-kickstarter/public_html');

// find a given user by its ID
$user = ApiAdminUser::findOne(1, $client);

// iterate all users
$users = ApiAdminUser::find()->setSort(['id' => SORT_ASC])->all($client);
foreach ($users->getModels() as $user) {
      echo $user->firstname . ' ' . $user->lastname;
}

Documentation

See the full Documentation in order to see how to make put, delete or post request, handle pagination or access the cms blocks.

Development and Contribution

Viewing all 3361 articles
Browse latest View live